Podemos asociar un nombre a un conjunto de filtros, y después aplicarlo al cargar datos (con find(), findAll(), etc, y en los dataprovider). Estos filtros con nombre son los scopes
class Entradas extends CActiveRecord { … public function scopes() { return array( 'aceptadas'=>array( 'condition'=>'aceptada=1', ), 'recientes'=>array( 'order'=>'fecha_alta DESC', 'limit'=>5, ), ); } … }
Para usarlo al cargar información:,
$entradas=Entradas::model()->aceptadas()->recientes()->findAll()
o
$provider=new CActiveProvider(Entradas::model()->recientes());
Se pueden definir filtros con parámetros, para tener mayor flexibilidad:
class Entradas extends CActiveRecord { … public function recientes($limite=5) { $this->getDbCriteria()->mergeWith(array( 'order'=>'fecha_alta DESC', 'limit'=>$limite, )); return $this; } … } //Por ejemplo, para cargar las 3 últimas entradas aceptadas $entradas=Entradas::model()->aceptadas()->recientes(3)->findAll()
Se pueden utilizar también al definir relaciones:
class Post extends CActiveRecord { … public function relations() { return array( … 'recentPublishedComments'=>array(self::BELONGS_TO, 'Post', 'post_id', 'scopes' => array('published', 'recent')), … ); } … } class User extends CActiveRecord { … public function relations() { return array( … 'posts'=>array(self::HAS_MANY, 'Post', 'author_id', 'with'=>'comments:approved'), … ); } … }
Se aplica a todas las búsquedas, aunque no se especifique explicitamente:
class Post extends CActiveRecord { … public function defaultScope() { return array( 'condition'=>"language='".Yii::app()->language."'", ); } … }
También se pueden aplicar con with():
$posts=Post::model()→published()→with('comments')→findAll(); … $posts=Post::model()→with('comments:published:today')→findAll(); </code>
Los scopes se aplican únicamente a las sentencias SELECT de sql, pero podemos cargar su definición para aplicarlos a otras sentencias:
Post::model()->deleteAll( Post::model->disabled()->getDbCriteria() ); // o también … $scopes=Post::model()->scopes(); Post::model()->deleteAll($scopes['disabled']); …
Si se quiere aplicar un nuevo scope, antes hay que llamar a resetScope()
… $old = Post::model()->published()->recently(); $new = Blog::model()->resetScope()->today();
Para evitar problemas de ambigüedad cuando se hacen accesos a varias tablas, se puede poner un alias a las condiciones:
public function scopes() { $t=$this->getTableAlias(false); //Devuelve el alias del modelo en la SQL return array( 'published'=>array('condition'=>"$t.published=1"), ); }