not saving pass attribute

I have the attribute pass that is not null in the database,then in model o want this pass required just on create scenario ,for that i have these rules in the model:


 public function rules() {

    	return array(

        	array('nome, username, email,country', 'required'),

        	array('receivenews', 'numerical', 'integerOnly' => true),

        	array('username,email', 'unique'),

        	array('nome, email', 'length', 'max' => 145),

        	array('username', 'length', 'max' => 45),

        	array('pass', 'length', 'max' => 95),

        	array('pass', 'required', 'on' => 'create'),

        	array('iduser, nome, username,country,receivenews, lastLogin, email, createDate', 'safe', 'on' => 'search'),

    	);

	}



my controller update action and loadmodel:


  public function loadModel($id) {


        $model = User::model()->findByPk($id);

    	if ($model === null || ($id != Yii::app()->user->id && !Yii::app()->user->checkAccess('Admin', Yii::app()->user->id)))

            throw new CHttpException(404, 'The requested page does not exist.');


        return $model;

    }




public function actionUpdate($id) {


        $model = $this->loadModel($id);

    	if (isset($_POST['User'])) {

        	$model->attributes = $_POST['User'];

        	if ($model->validate()) {

                if ($model->isOriginalPass()) {

                    $model->saveAttributes(array('nome', 'email', 'country', 'username', 'receivenews'));

                } else {

                    $model->save();

                }

                Yii::app()->user->setFlash('success', Yii::t('app', 'Data saved'));

            	$this->redirect(array('view', 'id' => $model->iduser));

            }

        }


        $this->render('update', array(

            'mostraPass' => false,

            'model' => $model

        ));

    }

Now on model->save i check the model->attributes and pass value is there but it wont save in database,why?

please post your model code, do you get any validation error

What is the function isOriginalPass()?

Are you sure you are getting to $model->save() instead of the other save without the pass attribute?

No validation error.

My entire model user code:




<?php


class User extends StyleStoreActiveRecord {


    public static function model($className=__CLASS__) {

    	return parent::model($className);

	}


    public function tableName() {

    	return 'user';

	}


	protected function afterValidate() {

    	parent::afterValidate();

		$this->pass = $this->encrypt($this->pass);

	}


    public function checkPass(){

		$utilizador=$this->findByAttributes(array('pass'=>$this->pass,'iduser'=>$this->iduser));

		if ($utilizador==null)

		{  

   		return false;

		}

		return true;

	}


   public function encrypt($value) {

    	return md5($value);

	}


	public function rules() {

    	return array(

            array('nome, username, email,country', 'required'),

            array('pass', 'required', 'on' => 'create'),

            array('receivenews', 'numerical', 'integerOnly' => true),

            array('username,email', 'unique'),

            array('nome, email', 'length', 'max' => 145),

            array('username', 'length', 'max' => 45),

            array('pass', 'length', 'max' => 95),

            array('pass', 'required', 'on' => 'create'),

   		array('iduser, nome, username, pass,country,receivenews, lastLogin, email, createDate', 'safe', 'on' => 'search'),

    	);

	}


    public function relations() {

    	return array(

        	'encomendas' => array(self::HAS_MANY, 'Encomenda', 'customer'),

    	);

	}


	public function afterSave() {

		if ($this->isNewRecord) {

		$role = new UserRole;

            $role->idUser = $this->iduser;

        	$role->RoleName = 'Customer';

        	$role->addRole();

        	$role->save();

    	}

	}


    public function attributeLabels() {

    	return array(

        	'iduser' => 'Iduser',

        	'nome' => Yii::t('app', 'Name'),

        	'username' => Yii::t('app', 'Username'),

        	'pass' => Yii::t('app', 'Password'),

        	'lastLogin' => Yii::t('app', 'Last Login'),

        	'email' => 'Email',

        	'country' => 'Country',

        	'receivenews' => Yii::t('app', 'Stay tuned about new styles'),

        	'createDate' => Yii::t('app', 'Create Date'),

    	);

	}


    public function search() {

    	$criteria = new CDbCriteria;

    	$criteria->compare('iduser', $this->iduser);

    	$criteria->compare('nome', $this->nome, true);

    	$criteria->compare('username', $this->username, true);

    	$criteria->compare('pass', $this->pass, true);

    	$criteria->compare('lastLogin', $this->lastLogin, true);

    	$criteria->compare('email', $this->email, true);

    	$criteria->compare('country', $this->country, true);

    	$criteria->compare('receivenews', $this->receivenews);

    	$criteria->compare('createDate', $this->createDate, true);

    	return new CActiveDataProvider($this, array(

                	'criteria' => $criteria,

            	));

	}

}

like you see here it’s the model instance:


public function loadModel($id) {


        $model = User::model()->findByPk($id);



NOTE: Please edit the above post it’s too long and has too much empty lines to be read… and there is no need to post all those commented lines at the beginning…

I think you did not understood my post…

I’m reffering to your code after the validation




   if ($model->isOriginalPass()) {

  	$model->saveAttributes(array('nome', 'email', 'country', 'username', 'receivenews'));

   } else {

      $model->save();

   }



So… are you sure that isOriginalPass() returns proper result and you get to the $model->save() instead to $model->saveAttributes() ?

yes it passes on $model->save()

I just noticed that you are encrypting the password in the afterValidate() method…

Note that save() before saving the data validates "again", so this time it would encrypt the already encrypted password and that value would get saved… did you check if the original value remains in the database or it gets replaced with some other value?

Dear friend,

What is being displayed in the ‘pass’ field, when you are updating.

Can you please display the code related to ‘pass’ in _form.php?

Please try the following, if everything is fine.




public function actionUpdate($id) 

    {


        $model = $this->loadModel($id);       


        if (isset($_POST['User'])) 

        {

            $model->attributes = $_POST['User'];

            if ($model->validate()) 

                {

                  if ($model->isOriginalPass())   

                    {

                       $model->saveAttributes(array('nome', 'email', 'country', 'username', 'receivenews'));

                    } 


                  else 


                    {

                       $model->setScenario('create');

                       $model->save();

                    }


                  Yii::app()->user->setFlash('success', Yii::t('app', 'Data saved'));

                  $this->redirect(array('view', 'id' => $model->iduser));

               }

         }


            $this->render('update', array('mostraPass' => false,'model' => $model));

    }






OR




public function actionUpdate($id) 

    {


        $model = $this->loadModel($id);

        $model->setScenario('create');


        if (isset($_POST['User'])) 

        {

            $model->attributes = $_POST['User'];

            if ($model->validate()) 

                {

                  if ($model->isOriginalPass())   

                    {

                       $model->saveAttributes(array('nome', 'email', 'country', 'username', 'receivenews'));

                    } 


                  else 


                    {

                       $model->save();

                    }


                  Yii::app()->user->setFlash('success', Yii::t('app', 'Data saved'));

                  $this->redirect(array('view', 'id' => $model->iduser));

               }

         }


            $this->render('update', array('mostraPass' => false,'model' => $model));

    }






yes you’re right mdomba.That’s the mistery. I have set


$model->save(false);

and now it’s fine thank you all

Dear friends,

The following are my inferences by going through this thread. Correct me If I am wrong.

1. If the pass is not changed upon update, the attributes ‘nome’, ‘email’, ‘country’, ‘username’,

and ‘receivenews’ are going to be validated and then saved in table. That looks fine.

2. If the pass is also changed, we are going to update all the attributes by

calling $model->save(false) without any validation. Is it a safe practice?

3. My contention is that if we set the scenario to "create", we can validate all the attributes including

"pass". Am I correct?

Can it be done in the following way?


public function actionUpdate($id) 

    {


        $model = $this->loadModel($id);


//SETTING THE SCENARIO HERE...

        $model->setScenario('create');


        if (isset($_POST['User'])) 

        {

            $model->attributes = $_POST['User'];

            if ($model->validate()) 

                {

                  if ($model->isOriginalPass())   

                    {

                       $model->saveAttributes(array('nome', 'email', 'country', 'username', 'receivenews'));

                    } 


                  else 


                    {

                       $model->save();

                    }


                  Yii::app()->user->setFlash('success', Yii::t('app', 'Data saved'));

                  $this->redirect(array('view', 'id' => $model->iduser));

               }

         }


            $this->render('update', array('mostraPass' => false,'model' => $model));

    }

@seenivasan

  1. Just a note here about saveAttributes() - it does not call before/afterSave and it does not validate the attributes - http://www.yiiframew…tributes-detail

  2. save(false) does not validate the model… but check the code it is validated before with $model->validate(), that’s why you can use later saveAttributes() or save(false) without problems.

  3. create scenario is for new records… why would we set "create" scenario on record update?

@zipzap

The originalPass() method is for searching the database to check if the password has been changed, considering that database calls are "expensive" it would be much more efficient to store the old password in a temporary variable and then compare with the actual value if it has changed.

Something like




$model = $this->loadModel($id);

$oldPass = $model->pass;

// as the password is hashed with md5() makes no sense to show that value in the input field

$model->pass = ''; 

if (isset($_POST['User'])) 

{

   $model->attributes = $_POST['User'];

   // now here in $oldPass is the original value and in $model->pass is the possible new value or empty if nothing entered

}



Yes indeed.

Thank you

Thank you very much. I have really learnt much by following this thread.

I appreciate the valuable inputs from my friend ZipZap and ever guiding Mdomba.