How can i sidestep current username and password of the user when updating his information? For example - when i try to update only the name it shows me that email is already taken and vice versa. That way i can not update only the or only the email, only both of them.
My actionUpdate:
public function actionUpdate()
{
$model = new UpdateForm();
$id = \Yii::$app->user->identity->id;
$user = $this->findModel($id);
//default values
$model->username = $user->username;
$model->email = $user->email;
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
if (isset($_POST['UpdateForm']))
{
$model->attributes = $_POST['UpdateForm'];
if($model->validate())
{
$user->username = $model->username;
$user->email = $model->email;
$user->password = md5($model->password);
$user->update();
$this->redirect(['view', 'id' => $user->id]);
}
}
else
{
return $this->render('update', [
'model' => $model,
]);
}
}
My UpdateForm rules:
public function rules()
{
return [
[['email', 'password', 'username'], 'required'],
[['email', 'password', 'username'], 'string', 'max' => 50],
[['image'], 'string', 'max' => 255],
[['username', 'password', 'email'], 'trim'],
['email', 'email'],
[[ 'email', 'username'], 'unique'],
];
}
Thank you in advance!
you should use both for unique
eg:
// a1 and a2 need to be unique together, and they both will receive error message
[['a1', 'a2'], 'unique', 'targetAttribute' => ['a1', 'a2']]
in your case
[[ 'email', 'username'], 'unique', 'targetAttribute' => ['email', 'username']],
http://www.yiiframework.com/doc-2.0/yii-validators-uniquevalidator.html
If you want to update the fields one at a time. You need to remove the required fields. He then checks that 3 must exist. Delete this line:
[['email', 'password', 'username'], 'required'],
So i reached the Ajax validation part. First i want to say that i read the answers of similar question but it did not helped me.
On registration form validation works good(when i try to register user with existing name it shows me error message), but when i am in the users profile and try to update his name with existing one nothing happens(no error shown).
My model UpdateForm.php rules:
public function rules()
{
return [
[['email', 'password', 'username'], 'required'],
[['email', 'password', 'username'], 'string', 'max' => 50],
[['image'], 'string', 'max' => 255],
['email', 'email'],
[[ 'email', 'username'], 'unique'],
];
}
My UserController action:
public function actionUpdate()
{
$id = \Yii::$app->user->identity->id;
$model = $this->findModel($id);
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
Will appreciate every advice!
configure yii_logger db in your machine (you can find it Yii2 docs).
then run
SELECT FROM_UNIXTIME(log_time, '%Y-%m-%d') log_date, y.* FROM yii_logger y where level = 1 order by log_time desc limit 20;
you may see error backtrace if your code is breaking somewhere.
I can add user successfully, For Password hashing I am using md5() But when I update user it is giving an error.
Here are the model rules:
public function rules()
{
return [
[['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status'], 'required'],
['email','email'],
[['confirm'], 'compare', 'compareAttribute' => 'password','on'=>'create'],
[['firstname', 'lastname', 'username', 'email', 'password', 'confirm', ], 'string', 'max' => 255],
];
}
In the form i.e. View, I am using following code:
<div class="form-group">
<?php
if($case == 'create') { //this condition called when create user
echo $form->field($model, 'password')->passwordInput([
'maxlength' => true,
'placeholder' => 'Enter the Password',
]);
}
else { // during update
echo $form->field($model, 'password')->passwordInput([
'maxlength' => true,
'placeholder' => 'Enter the Password',
'value' => '',
]);
}
?>
</div>
<div class="form-group">
<?= $form->field($model, 'confirm')->passwordInput([
'maxlength' => true,
'placeholder' => 'Confirm Password',
]) ?>
</div>
and in controller I am using following code:
public function actionUpdate($id)
{
$model = $this->findModel($id);
$case = "update";
if ($model->load(Yii::$app->request->post())) {
$model->save();
return $this->redirect(['view', 'id' => $model->id]);
}
else {
return $this->render('update', [
'model' => $model,
'all_users_array' => $all_users_array,
'all_groups_array' => $all_groups_array,
'case' => $case,
]);
}
}
I am getting the error:
Undefined offset: 1 Failed to prepare SQL: UPDATE xbox_user SET
password=:qp0, role=:qp1, modified=:qp2, status=:qp3 WHERE
id=:qp4
Can anyone please let me what code should be modified there?
Thank you!
It is better to use scenarios in your case and use rules() too for other requirements, In Users.php model file write the following code:
public function scenarios(){
$scenarios = parent::scenarios();
$scenarios['create'] = ['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status', 'password','confirm'];
$scenarios['update'] = ['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status'];
return $scenarios;
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status', 'password','confirm'], 'required'],
['email', 'filter', 'filter' => 'trim'],
['email', 'unique' ],
['email', 'unique' ,'targetAttribute' => 'email'],
['email', 'required'],
['email', 'email'],
['email', 'unique', 'targetClass' => '\common\models\Users', 'message' => 'This email address has already been taken.'],
['confirm', 'compare', 'compareAttribute'=>'password', 'message'=>"Passwords does not match." ],
[['firstname', 'lastname', 'username', 'email', 'password', 'confirm', ], 'string', 'max' => 255],
];
}
In your views file use the following code:
<div class="form-group">
<?php
if($case == 'create'){
echo $form->field($model, 'password')->passwordInput(['maxlength' => true,'placeholder'=>'Enter the Password']);
}
else{
echo $form->field($model, 'password')->passwordInput(['maxlength' => true,'placeholder'=>'Enter the Password']);
}
?>
</div>
<div class="form-group">
<?= $form->field($model, 'confirm')->passwordInput(['maxlength' =>true,'placeholder'=>'Confirm Password']) ?>
</div>
and in your controller file, UsersController.php use the following code:
public function actionUpdate($id)
{
$model = $this->findModel($id);
$model->scenario = 'update'; // calling scenario of update
if ($model->load(Yii::$app->request->post())) {
$req_array = yii::$app->request->post();
$role = $req_array['Users']['role'][0];
$model->role = $role;
if($req_array['Users']['password'] !== $req_array['Users']['confirm'])
{
$model->addError('confirm','Password and Confirm should be same.');
$model->password = $req_array['Users']['password'];
$model->confirm = $req_array['Users']['confirm'];
return $this->render('update', [
'model' => $model,
'all_users_array'=>$all_users_array,
'all_groups_array'=>$all_groups_array,
'case'=>$case,
]);
}
elseif( ($req_array['Users']['password'] == $req_array['Users']['confirm']) && (!empty($req_array['Users']['password'])))
{
$model->password = MD5($req_array['Users']['password']);
$model->save();
return $this->redirect(['view', 'id' => $model->id]);
}
else
{
$model->save();
return $this->redirect(['view', 'id' => $model->id]);
}
} else {
$model->password = '';
return $this->render('update', [
'model' => $model,
'all_users_array'=>$all_users_array,
'all_groups_array'=>$all_groups_array,
'case'=>$case,
]);
}
}
Using this code, you will not get error of required password in update, In case if you fill the password then process of confirm password and required will be run.
Hope this helps for you.
User Model
public function rules()
{
return [
[['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status'], 'required'],
['email','email'],
[['password', 'confirm'], 'required', 'on' => 'create'],
['confirm', 'compare', 'compareAttribute' => 'password', 'message'=>"Passwords does not match." ],
[['firstname', 'lastname', 'username', 'email', 'password', 'confirm', ], 'string', 'max' => 255],
];
}
Update Action
public function actionUpdate($id)
{
$model = $this->findModel($id);
$model->passowrd = '';
$model->confirm = '';
if ($model->load(Yii::$app->request->post())) {
$model->role = $model->role[0];
if (empty($model->password) || empty($model->confirm)) {
$model->password = $model->getOldAttribute('password');
$model->confirm = $model->getOldAttribute('confirm');
}
if ($model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
} else {
return $this->render('update', [
'model' => $model,
'all_users_array'=>$all_users_array,
'all_groups_array'=>$all_groups_array,
]);
}
}
Form
<div class="form-group">
<?= $form->field($model, 'password')->passwordInput(['maxlength' => true,'placeholder'=>'Enter the Password']) ?>
</div>
<div class="form-group">
<?= $form->field($model, 'confirm')->passwordInput(['maxlength' => true,'placeholder'=>'Confirm Password']) ?>
</div>
First try this one
[['confirm'], 'compare', 'compareAttribute' => 'password','on'=>'create']
if not work then please follow the following steps create your scenario for updation and don't compare password
Did you try scenarios.. i will give a simple example for user registration and user login i hope it will help you
<?php
class User extends Model
{
public $name;
public $email;
public $password;
public function rules(){
return [
[['name','email','password'],'required'],
['email','email'],
[['name', 'email', 'password'], 'required', 'on' => 'register'],
];
}
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios['login'] = ['name','password'];//Scenario Values Only Accepted
return $scenarios;
}
}
?>
Apply Scenario For Model
See the below code, We added two ways of setting the scenario of a model. By default, scenario will support the model rules.
<?php
class UserController extends Controller
{
// APPLY SCENARIOS
// scenario is set as a property
public function actionLogin(){
$model = new User;
$model->scenario = 'login';
}
// scenario is set through configuration
public function actionRegister(){
$model = new User(['scenario' => 'register']);
}
}
?>
I have my own basic User model i reuse for most projects, which handles updating new password or leaving the previous one if no password is provided by the update form. Also implements IdentityInterface so it can be used for login to the Application.
My basic User model:
<?php
namespace app\models;
use Yii;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
class User extends ActiveRecord implements IdentityInterface {
const SCENARIO_LOGIN = 'login';
const SCENARIO_CREATE = 'create';
const SCENARIO_UPDATE = 'update';
// We use $hash to save the hashed password we already have saved in the DB
public $hash;
public $password_repeat;
/**
* #inheritdoc
*/
public static function tableName() {
return 'user';
}
/**
* #inheritdoc
*/
public function scenarios() {
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_LOGIN] = ['user', 'password'];
$scenarios[self::SCENARIO_CREATE] = ['user', 'password', 'password_repeat', 'email', 'authKey'];
$scenarios[self::SCENARIO_UPDATE] = ['user', 'password', 'password_repeat', 'email'];
return $scenarios;
}
/**
* #inheritdoc
*/
public function rules() {
return [
[['user'], 'string', 'max' => 45],
[['email'], 'string', 'max' => 45],
[['email'], 'email'],
[['password', 'password_repeat'], 'string', 'max' => 60],
[['authKey'], 'string', 'max' => 32],
[['user', 'password'], 'required', 'on' => self::SCENARIO_LOGIN],
[['user', 'password', 'password_repeat', 'email'], 'required', 'on' => self::SCENARIO_CREATE],
[['user', 'email'], 'required', 'on' => self::SCENARIO_UPDATE],
// Generate a random String with 32 characters to use as AuthKey
[['authKey'], 'default', 'on' => self::SCENARIO_CREATE, 'value' => Yii::$app->getSecurity()->generateRandomString()],
[['password'], 'compare', 'on' => self::SCENARIO_CREATE, 'skipOnEmpty' => true],
[['user'], 'unique'],
];
}
/**
* #inheritdoc
*/
public function attributeLabels() {
return [
'id' => 'Id',
'user' => 'User',
'password' => 'Password',
'authKey' => 'AuthKey',
'email' => 'Email',
];
}
/**
* #inheritdoc
*/
public function beforeSave($insert) {
if (parent::beforeSave($insert)) {
if($insert) {
$this->password = Yii::$app->getSecurity()->generatePasswordHash($this->password);
}
else {
if(strlen($this->password) > 0) {
$this->password = Yii::$app->getSecurity()->generatePasswordHash($this->password);
}
else {
$this->password = $this->hash;
}
}
return true;
}
return false;
}
/**
* #inheritdoc
*/
public function afterFind() {
$this->hash = $this->password;
$this->password = '';
parent::afterFind();
}
/**
* #inheritdoc
*/
public static function findIdentity($id) {
return self::findOne($id);
}
/**
* #inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null) {
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}
/**
* #inheritdoc
*/
public static function findByUsername($username) {
$model = static::findOne(['user' => $username]);
return $model;
}
/**
* #inheritdoc
*/
public function getId() {
return $this->getPrimaryKey();
}
/**
* #inheritdoc
*/
public function getAuthKey() {
return $this->authKey;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey) {
return $this->authKey === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password) {
return Yii::$app->getSecurity()->validatePassword($password, $this->hash);
}
}
This way you only need to use the corresponding scenario in your create, update and login actions:
$model->scenario = User::SCENARIO_LOGIN;
$model->scenario = User::SCENARIO_CREATE;
$model->scenario = User::SCENARIO_UPDATE;
I have table student and table user that user_id foreign Key table student. I want to save information from student and create user and set id user into user_id in table student
student models:
class Student extends \yii\db\ActiveRecord
{
public $username;
public $password;
public $email;
......
public function rules()
{
return [
[['name', 'lastname', 'tell', 'mobile', 'codemeli', 'birthday' , 'jensiyat', 'address', 'fatherName', 'user_id', 'created'], 'required'],
[['tell', 'mobile', 'codemeli', 'postcode', 'number', 'user_id', 'salary', 'remove'], 'integer'],
['address', 'string'],
['pic','file'],
['username','string'],
['password','string'],
['email','string'],
[['username','password'],'required'],
['email','unique'],
['email','email'],
[['created', 'salary', 'postcode'], 'safe'],
[['name', 'lastname', 'fatherName', 'level'], 'string', 'max' => 50],
[['birthday'], 'string', 'max' => 10],
[['number', 'user_id'], 'unique', 'targetAttribute' => ['number', 'user_id'], 'message' => 'The combination of Number and User ID has already been taken.'],
[['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
];
}
.........
public function beforeSave($insert)
{
if (parent::beforeSave($insert)) {
$user = new User;
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
$ret=$user->save();
$this->user_id = $user->id;
return $ret ? $user : null;
}
}
actionCreate:
public function actionCreate()
{
$model = new Student();
if ($model->load(Yii::$app->request->post())) {
// $model->
$model->pic = UploadedFile::getInstance($model, 'pic');
$username = Yii::$app->request->post('username');
$password = Yii::$app->request->post('password');
$email = Yii::$app->request->post('email');
$model->created = time();
$model->number = 0;
$model->remove = 1;
$model->level = 0;
$model->salary = 0;
if (!empty($model->pic->extension)) {
$name = time() . '.' . $model->pic->extension;
$model->pic = $name;
if ($model->save()) {
$model->img->saveAs('uploads/' . $name);
}
}
var_dump($model->getErrors());
die();
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
I'm trying to learn yii 2.0 by creating a simple form for adding new posts.
Here's the respective method in my SiteController (have also added use app\models\Posts; at the top):
public function actionSave($id=NULL){
if($id = NULL)
$model = new Posts;
else
$model = $this->loadModel($id);
if(isset($_POST['Posts'])){
$model->load($_POST);
if($model->save()){
Yii::$app->session->setFlash('success', 'Model has been saved');
$this->redirect($this->createUrl('site/save', ['id' => $model->id]));
}else
Yii::$app->session->setFlash('error', 'Model could not be saved');
}
echo $this->render('save', ['model' => $model]);
}
It renders save view file. Here's that view file:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(['options' => ['class' => 'form-horizontal', 'role' => 'form']]) ?>
<div class="form-group">
<?php echo $form->field($model, 'title')->textInput(['class' => 'form-control']); ?>
</div>
<div class="form-group">
<?php echo $form->field($model, 'data')->textArea(['class' => 'form-control']); ?>
</div>
<?php echo Html::submitButton('Submit', ['class' => 'btn btn-primary pull-right']); ?>
<?php ActiveForm::end();
I'm expecting a form, but it's showing an error Calling unknown method: yii\db\ActiveQuery::formName()
What am i doing wrong here?
public function actionSave($id=NULL){
if($id == NULL)
$model = new Posts;
else
$model = $this->loadModel($id);
if(isset($_POST['Posts'])){
$model->load($_POST);
if($model->save()){
Yii::$app->session->setFlash('success', 'Model has been saved');
//Updated
$this->redirect(['save', 'id' =>$model->id]);
//Remove this
//$this->redirect($this->createUrl('site/save', ['id' => $model->id]));
}else
Yii::$app->session->setFlash('error', 'Model could not be saved');
}
echo $this->render('save', ['model' => $model]);
}
I suppose you use the loadModel function, if so, change this line
$model = Posts::find($id);
to this
$model = Posts::find()->where(['id' => $id])->one();
The error occurs because the object returned by loadModel is a ActiveQuery and the ActiveForm expected a ActiveRecord.
Calling unknown method: frontend\models\SignupForm::save()
SiteController.php
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$fileName = $model->username;
$model->file =UploadedFile::getInstance($model,'file');
$model->file->saveAs('uploads/'.$fileName.'.'.$model->file->extension );
$model->filePath = 'uploads/'.$fileName.'.'.$model->file->extension ;
$model->save();
return $this->redirect(['view', 'id' => $model->idQuiz]);
//}
// if ($model->load(Yii::$app->request->post())) {
if ($user = $model->signup()) {
if (Yii::$app->getUser()->login($user)) {
return $this->goHome();
}
}
}
return $this->render('signup', [
'model' => $model,
]);
}
signup.php
<?= $form->field($model, 'file')-> fileinput(); ?>
SignupForm.php
<?php
namespace frontend\models;
use common\models\User;
use yii\base\Model;
use Yii;
/**
* Signup form
*/
class SignupForm extends Model
{
public $username;
public $email;
public $password;
public $first_name;
public $last_name;
public $address;
public $state_id;
public $city_id;
public $file;
public $filePath;
/**
* #inheritdoc
*/
public function rules()
{
return [
['username', 'filter', 'filter' => 'trim'],
['username', 'required'],
['first_name', 'required'],
['last_name', 'required'],
['address', 'required'],
['state_id', 'required'],
['city_id', 'required'],
['filePath', 'required'],
['username', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This username has already been taken.'],
['username', 'string', 'min' => 2, 'max' => 255],
['email', 'filter', 'filter' => 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'string', 'max' => 255],
['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken.'],
['password', 'required'],
['password', 'string', 'min' => 6],
];
}
/**
* Signs user up.
*
* #return User|null the saved model or null if saving fails
*/
public function signup()
{
if (!$this->validate()) {
return null;
}
$user = new User();
$user->first_name = $this->first_name;
$user->last_name = $this->last_name;
$user->address = $this->address;
$user->state_id = $this->state_id;
$user->city_id = $this->city_id;
$user->filePath = $this->filePath;
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
return $user->save() ? $user : null;
}
}