CGridView. Поиск и сортировка по полю связанной таблицы

В этом топике пойдет речь о поиске/сортировке столбцов из связанной таблицы в CGridView.
Существует не один вариант решения, рассмотрим вариант, предложенный здесь.



Что имеем

У нас есть две таблицы: комментарии и статьи (используем тестовый демо-блог Yii). У каждого комментария есть поле post_id, ссылающееся на статью. В итоге мы хотим вывести грид с комментариями, где вместо ИД статьи будет поле с ее наименованием + сортировка/поиск по полю.

Решение

1) Проверяем, описана ли связь в relations:
'post' => array(self::BELONGS_TO, 'Post', 'post_id'),

2) Добавляем описание нового поля:
private $_postTitle = null;
public function getPostTitle() {
    if ($this->_postTitle === null && $this->post !== null) {
        $this->_postTitle = $this->post->title;
    }
    return $this->_postTitle;
}
public function setPostTitle($value)
{
    $this->_postTitle = $value;
}

3) Добавляем правило для созданного поля в rules для сценария search:
public function rules() {
    return array(
        array('content, author, email', 'required'),
        array('author, email, url', 'length', 'max'=>128),
        array('email','email'),
        array('url','url')
 
        array('content, postTitle, status, author', 'safe', 'on'=>'search'),
    );
}

4) Не забываем также описать атрибут:
'postTitle' => 'Статья',

5) Добавляем экшн:
    public function actionIndex() {
        $model = new Comment('search');
        $model->unsetAttributes();
        if (isset($_GET['Comment']))
            $model->attributes = $_GET['Comment'];

        $this->render('index', array(
            'model' => $model,
        ));
    }

6) В экшне мы используем вызов модели со сценарием search. Его нам нужно подкорректировать. Собственно, сейчам мы и добавляем сортировку и поиск по полю из связанной таблицы.
    public function search() {
        $criteria = new CDbCriteria;
        $criteria->with = "post"; // указываем связанный объект, который должен быть загружен вместе с текущим объектом

        $criteria->compare('content', $this->content, true);
        $criteria->compare('status', $this->status);
        $criteria->compare('author', $this->author, true);
        $criteria->compare('post.title', $this->postTitle, true); // добавляем критерий поиска по связанному полю. Во избежание ошибок или при использовании нескольких связанных объектов, рекомендуется проставить для всех колонок алиасы таблиц(например, "t.content", "post.title")

        $sort = new CSort();
        $sort->defaultOrder = 't.id DESC'; // устанавливаем сортировку по умолчанию
        $sort->attributes['postTitle'] = array( // добавляем сортировку по postTitle
                'asc' => 'post.title',
                'desc' => 'post.title desc',
            );
        return new CActiveDataProvider($this, array(
                    'criteria' => $criteria,
                    'sort' => $sort
                ));
    }

7) И, наконец, вызов грида в представлении:
$this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider' => $model->search(),
    'filter' => $model,
    'columns' => array(
        'content',
        'postTitle',
        'status',
        'author',
    ),
));

На самом деле, этот способ показался мне несколько длинным, однако все же полезным в некоторых случаях :)

Комментарии

  1. У меня заработало
    не
    private $_postTitle = null;
    а
    public $postTitle = null;
    и я удалил функции
    public function getPostTitle() {
    if ($this->_postTitle === null && $this->post !== null) {
    $this->_postTitle = $this->post->title;
    }
    return $this->_postTitle;
    }
    public function setPostTitle($value)
    {
    $this->_postTitle = $value;
    }

    Зачем эти функции?

    Система авторизации пользователей на Yii http://accessnetwork.ru

    ОтветитьУдалить

Отправить комментарий

Популярные сообщения