using named scopes with delete and update

I tried using named scopes like this in my AR object


	public function scopes()

	{

		return array(

			'primary'=>array(

				'condition'=>'is_primary=1'

			),

		);

	}

then, in my controller I do this


Email::model()->primary()->delete();

but when I check the log Yii try to do this


DELETE FROM `email` WHERE `email`.`id` IS NULL

when use with find(), it works though


Querying SQL: SELECT * FROM `email` `t` WHERE is_primary=1 LIMIT 1

The Yii guide says named scopes support update and delete method, am i missing anything?

Hello sumwai,

CActiveRecord::delete is for a single model. Named scopes should work when using CActiveRecord::deleteAll.

Now that I think about it, it should also work with delete if it works with find, weird…

Hi Chris, thanks for replying.

I tried with deleteAll too, but still it doesn’t work for me :S

with


Email::model()->primary()->deleteAll();

I get this


Executing SQL: DELETE FROM `email`

delete will delete the actual instance of the active record, it will not works on a newly create record or a CActiveRecord::model() record.

About delete all, I have no idea.

I give up, the closest thing I can make deleteAll or updateAll works with named scopes is something like




Email::model()->deleteAll(

  Email::model->primary()->getDbCriteria()

);



Anybody else has any thought?

I think that your is a good solution.

Is just strange that in the documentatio there is no reference to the fact that named scopes works only in find.

That’s actually a clever solution! :)

Which version of Yii are you running sumwai?

1.1.5

I might be wrong, but I think, that’s a bug in the docs. From the AR source code i can’t see where scopes are applied for delete*() commands.

BTW i’ve used exactly the same solution like you did in a similar situation for a find command. Only problem i see: It makes the code harder to understand. So now i’m using this approach instead:




$scopes=Email::model()->scopes();

Email::model()->deleteAll($scopes['primary']);

Remember, a scope consists of the property values for a CDbCriteria. So you can use the array values of scopes() and throw them at pretty much any AR method you want.

Thanks! it looks cleaner this way.

An easy way around this is to add the following function to your base active record class:




	/**

	 * Deletes rows with the specified condition, after applying existing scopes

	 * See {@link find()} for detailed explanation about $condition and $params.

	 * @param mixed $condition query condition or criteria.

	 * @param array $params parameters to be bound to an SQL statement.

	 * @return integer the number of rows deleted

	 */

	public function deleteAllWithScopes($condition='',$params=array())

	{

		Yii::trace(get_class($this).'.deleteAllWithScopes()',

				'system.db.ar.CustomCActiveRecord');

		$builder=$this->getCommandBuilder();

		$criteria=$builder->createCriteria($condition,$params);

		

		$this->applyScopes($criteria);

		

		$command=$builder->createDeleteCommand($this->getTableSchema(),$criteria);

		return $command->execute();

	}



I really feel deleteAll() should use scopes. Would there be any problem if I just overload the deleteAll() instead of a new function called deleteWithScopes()?

http://code.google.c…s/detail?id=649

I’m not clear on the reasoning for why it’s a “WontFix”

EDIT:

I did just notice: http://www.yiiframework.com/files/CHANGELOG-1.0.6.txt

It says it’s updated there to work for update and delete.