===== CactiveRecord : scopes =====
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'),
…
);
}
…
}
=== Default scope ===
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();
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"),
);
}