Портфолио
Разработка сайтов Продвижение сайтов Маркетинг Дизайн
Контакты

вернуться

Yii Scopes - зачем и как их использовать?

Yii Scopes, или именованная группа условий, используется для упрощения работы с моделями. Позволяет сократить строки кода, по-средством уменьшения написания запросов к моделям. Их легко использовать в отношениях, и обычно используют для модификации применения функции find(). Можно их назвать как поисковые фильтры.

Scopes можно определить в виде массива именованных параметров. Например:

class Model extends CActiveRecord
{
    …
    public function scopes()
    {
        return array(
            'published'=>array(
                'condition'=>'statusKey = "publish"',
            ),
            'recently'=>array(
                'order'=>'dateCreate DESC',
                'limit'=>5,
            ),
        );
    }
    …
}

 Теперь когда необходимо получить все опубликованные модели, можно указать следующее:

$models = Model::model()->published()->findAll();

Разные scopes модели можно использовать совместно:

$models = Model::model()->published()->recently()->findAll();

Yii Scopes можно задавать с параметрами, для этого они определяются в классе как методы, например:

public function recently( $limit = 5 )
{
    $this->getDbCriteria()->mergeWith(array(
        'order' => 'dateCreate DESC',
        'limit' => $limit,
    ));
    return $this;
}
public function published( $limit = 5 )
{
    $this->getDbCriteria()->mergeWith(array(
        'condition' => 'statusKey = "publish"',
        'limit' => $limit,
    ));
    return $this;
}

Тогда в коде можно использовать:

$models = Model::model()->published(5)->findAll();

Плюс scopes можно указывать и в отношениях модели. Например:

class Post extends CActiveRecord
{
    …
    public function relations()
    {
        return array(
        …
             'recentPublishedComments'=>array(self::BELONGS_TO, 'Post', 'postId', 'scopes' => array('published', 'recent')),
        …
        );
    }
    …
}

При этом scopes можно и определять в параметре with().

$posts = Post::model()->with('comments:recently:approved')->findAll();

Есть возможность определить дефолтный scope для модели, который будет срабатывать при использовании find() или findAll():

public function defaultScope()
{
    return array(
            'order'=>'dateUpdate DESC',
            'condition'=>'active = 1',
    );
}

Чтобы сделать выборку по новым параметрам, сбросив параметры старой выборки, можно использовать resetScopes()

$old = Post::model()->published()->recently();
$new = Post::model()->resetScope()->today();

Следите за тем, чтобы названия столбцов не конфликтовали в scopes, для этого достаточно указывать явно название таблицы в выборке:

public function scopes()
{
    $t=$this->getTableAlias(false);
    return array(
        'published'=>array('condition'=>$t.".published = 1"),
    );
}
public function scopes()
{
    return array(
        'published'=>array('condition'=>"t.published=1"),
    );
}

Использование scopes в приниципе удобно и полезно, только следует помнить что кое-где можно воспользоваться, а может даже и нужно, и стандартными поисками Yii или CDbCriteria.