Reputation: 2600
PROBLEM 1:
When I try to save()
any Yii Model, it updates all fields in the row.
The problem is: When I try to save model users, even if has no PASSWORD to update, it get the database value(already hashed) and hash again.
How can I do to YII only update fields that I want?
Code:
$user = Users::model()->findByAttributes(array('username'=>$this->username));
$user->ip = $_SERVER['REMOTE_ADDR'];
$user->save();
Users.php (Model):
public function beforeSave() {
if (!empty($this->password))
$this->password=$this->hashPassword($this->password);
return true;
}
PROBLEM 2:
I have an API that can create USERS. API Tutorial: http://www.yiiframework.com/wiki/175/how-to-create-a-rest-api/
When I have crypter_password in the database, instead password, I got the error: Parameter password is not allowed for model Users
, because the API validate parameters using $model->hasAttribute()
.
How can I fix the API actionCreate
to allow custom parameters?
Upvotes: 2
Views: 4315
Reputation: 8140
Eventhough the other answers listed here are not wrong, they are definitely not really developer friendly and it's extremely easy to forget to add the attributes to the save line.
Here is a developer friendly way of working.
In your model, add the following attribute:
private $_aAttributesBackup;
In this variable, we will store an exact copy of the current model. To do this, the following afterFind method needs to be added:
public function afterFind()
{
$this->_aAttributesBackup = $this->attributes;
}
Almost there. At this point, the model will store all of his attributes in the attributesBackup field which makes it easier to compare. To make it easier, we also need a method that will check if the specified attribute has a backup value. We do this by adding the following code into our model:
public function getOriginalAttribute($sAttribute)
{
if ($this->_aAttributesBackup)
{
return $this->_aAttributesBackup[$sAttribute];
}
return NULL;
}
Now, how about checking if the password has been changed? Simple, by adding the following beforeSave code:
public function beforeSave()
{
if ($this->getOriginalAttribute('password') != $this->password)
{
$this->password = sha1($this->password);
}
return parent::beforeSave();
}
Et voila. Now everytime you execute the code $Model->save(); the system will check if the password has been changed, If the password is changed, it will hash it again, if it is not changed, it won't be hashed again.
Upvotes: 0
Reputation: 7419
Save ()
inserts a row into the database table if its isNewRecord
property is true
. Otherwise, it will update the corresponding row in the table (usually the case if the record is obtained using one of those 'find' methods.)
What you have to do is update specific field so you can use SaveAttributes
and it accepts the array of string values that have been updated for example demo code is as follow
$user = Users::model()->findByAttributes(array('username'=>$this->username));
$user->ip = $_SERVER['REMOTE_ADDR'];
$user->SaveAttributes(array('ip'));
Upvotes: 0
Reputation: 2591
According to Yii's doc: http://www.yiiframework.com/doc/api/1.1/CActiveRecord#save-detail
public boolean save(boolean $runValidation=true, array $attributes=NULL)
$attributes - array - list of attributes that need to be saved. Defaults to null, meaning all attributes that are loaded from DB will be saved.
You can pass in an array of fields that you want to save.
Upvotes: 1