How to update a specific model attribute?

I’m pretty new to Yii.Though I find Yii is great,I’m quite confused with writing codes myself some time.For example,I want to do run such a sql:

"UPDATE profile SET avatar=‘newValue’ WHERE avatar=‘oldValue’ and user_id=100 ";

Then how can I turn it into CActiveRecord?Is it something like this? Or there is a better way?

Thank You For Your Reply In Advance! I’m new and it seems that I cannot reply you right now according to the rules.




$model = new Profile;

$avatar=$model->findByAttributes(array('avatar'=>'oldValue','user_id'=>100));

$avatar->attributes=array('avatar'=>'newValue');

$avatar->save();



This code looks ok.

One thing you can do is skip the new Profile part - you are really just loading an existing model, not creating a new one.




$avatar=Profile::model()->findByAttributes(array('avatar'=>'oldValue','user_id'=>100));

$avatar->attributes=array('avatar'=>'newValue');

$avatar->save();



You should also put some error handling code in there (if user_id invalid, etc) but this is a good example.

/* moved to general discussion - not a tip, snippet or tutorial */

Is there any way to do this via updateAll() or updateByPk()? The reason I ask is because I have a similar situation but I want to use massive assignment, and I’m having problems with the $model->attributes() array always containing even columns that must not be changed.

my rules():


array('username, password, expire_date', 'required', 'on'=>'insert'),

array('username, expire_date', 'required', 'on'=>'update'),

array('user_id', 'numerical', 'integerOnly'=>true, 'on'=>'insert'),

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

array('username', 'unique', 'allowEmpty'=>false, 'caseSensitive'=>false, 'on'=>'insert'),

array('password', 'length', 'max'=>255),


array('user_id, username, password, create_date, expire_date', 'safe', 'on'=>'search'),



my controller:




$model2= new UserLogins('update');

$model2->setScenario('update'); // Just making sure I'm on the "update" scenario

#$model2->unsetAttributes(); // Tried this one to delete all attributes, also tried "unset($model2->attributes) no luck


$model2->username = $_POST['UserLogins']['username'][$index];

if ( isset($_POST['UserLogins']['password'][$index]) && !empty($_POST['UserLogins']['password'][$index]) ){

	// If password is set, change it, if not don't touch it.

	$model2->password = crypt($_POST['UserLogins']['password'][$index], Randomness::blowfishSalt());

}else{

	$model2->password = null;

}

$model2->expire_date = $_POST['UserLogins']['expire_date'][$index];


$model2->attributes = Array();

echo "<pre>model2->attributes is:<br>";

echo var_dump($model2->attributes);

echo "</pre>";


$model2->updateAll($model2->attributes,'user_login_id='.$currLoginId[0]['user_login_id']); //This gives me error about foreign key constraints



My var_dump() is always showing this:




model2->attributes is:

array(6) {

  ["username"]=>

  string(7) "rrahim1"

  ["password"]=>

  NULL

  ["expire_date"]=>

  string(10) "2012-07-27"

  ["user_login_id"]=>

  NULL

  ["user_id"]=>

  NULL

  ["create_date"]=>

  NULL

}

My goal is to have $model2->attributes that only has full values and no NULL fields at all. Why? Because my database complains if the updateAll() has columns that are used on other tables as foreign keys.

Can someone show me how I would achieve this?

Thank you in advance.

user


$model->update(array('condition'=>"your_conditions",$attributes));

this will update a specific value in your db.:)

I think it is enough. Am I right?




$model=Profile::model()->findByAttributes(array('avatar'=>'oldValue','user_id'=>100));

$model->avatar= 'newValue';

$model->save();



Yeah its the same thing.

But can you see from that code.

  1. you will run a select query to get a record and then you will save a new value.

  2. Your proposed solution doesn’t work in the different model scenario.

Thanks for the tip, jayant, I tried your code but I keep getting errors:

Variant 1):




$model2->update( array('condition'=>"user_login_id=".$currentLoginId, $attributes) )


//This is returned:

//	PHP notice

//	Undefined variable: attributes 



Variant 2):




$model2->update( array('condition'=>"user_login_id=".$currentLoginId, $model2->attributes) )


//This is returned:

//	PHP warning

//	property_exists() expects parameter 2 to be string, array given 

//The update() is passed the following (as shown in the Yii stack trace:

// 	CActiveRecord->update(array("condition" => "user_login_id=2",

//    	0 => array("username" => "username123", "password" => null, "expire_date" => "2012-07-27", "user_login_id" => null, ...))) 



In Variant 2, could the problem be that $model2->attributes is returning an multidimensional array that starts with 0?

Any reason this would not be working?

Thank you very much for your help! I appreciate it.

I fixed it my way. Basically, I took @Srinivasan’s suggestion and @jayant’s suggestion and brought them together. My issue was that I was not querying the model first to get the ->attributes and modify them later, that’s why AR was complaining about failing to update the row citing that it was missing a lot of attributes.

This is the relevant code that works now:




// Find all User Logins ($model2) based on a given $user_id

$relatedUserLogins = $model2->findAll(array('order'=>'user_login_id ASC','condition'=>'user_id=:user_id','params'=>array(':user_id'=>$model1->user_id)));


foreach($index=0; $index<count($loginCount); $index++){

	$currLoginId = $relatedUserLogins[$index]['user_login_id'];

	$model2->unsetAttributes(); // Clear the attributes because earlier I was foreach()-ing them to validate them


	// Query the User Logins model ($model2)

	$model2 = $model2->find(array('order'=>'user_login_id ASC','condition'=>'user_login_id=:user_login_id','params'=>array(':user_login_id'=>$currLoginId)));


	// Only wanted to update these 3 attributes, AR wanted the full attribute list (create_date, user_id, etc.)

	$model2->username = $_POST['UserLogins']['username'][$index];

	$model2->password = crypt($_POST['UserLogins']['password'][$index], Randomness::blowfishSalt());

	$model2->expire_date = $_POST['UserLogins']['expire_date'][$index];


	if ( $model2->update('user_login_id='.$currLoginId, $model2->attributes) ){

    	// Redirect because update was successull

    	

    	// Basically what happened here was I stored the ->attributes from the DB, then I overwrote

    	// only the attributes that were changed, leaving everything else as they were in DB.

	}

}//end: foreach()



Hopefully this helps someone in using this great framework called "Yii"! I love it myself!

Best regards!

Hi,

Some body refer to this code:




$avatar=Profile::model()->findByAttributes(array('avatar'=>'oldValue','user_id'=>100));

$avatar->attributes=array('avatar'=>'newValue');

$avatar->save();



I want to say, top code get two query from database(SELECT and UPDATE), but you can use this code for just get one query(UPDATE):




$criteria = new CDbCriteria();

$criteria->compare('avatar', 'oldValue');

$criteria->compare('user_id', 100);

Profile::model()->updateAll(array('avatar'=>'newValue'), $criteria);



Note for this method, the attributes are not checked for safety and no validation is done.

Thanks

Nabi