Постраничный вывод в CGridView

Общие вопросы по использованию фреймворка. Если не знаете как что-то сделать и это про Yii, вам сюда.
Ответить
Аватара пользователя
Faenir
Сообщения: 292
Зарегистрирован: 2010.01.06, 01:46
Откуда: Симферополь

Постраничный вывод в CGridView

Сообщение Faenir »

Добрый день.
Есть страница, на которой выводятся все записи из нескольких связанных таблиц БД.
Вроде все работает, но есть одна проблема: выводится неправильное количество записей на странице.
'pageSize' вроде выставлен 10, а выводится на первой странице "Элементы 1—5 из 12.", а на второй "Элементы 6—12 из 12."
Причем, начинает выводиться правильное количество записей, если отключить "together"... но в таком случае у меня не получается сделать фильтрацию по элементам из связанных таблиц.
С Yii работаю пару недель... причем это мой первый фреймворк вообще. Что я делаю не так? Помогите пожалуйста.

Вот код из модели:

Код: Выделить всё

public function search()
    {
        $criteria = new CDbCriteria;

        $criteria->with = array('genres', 'styles', 'country');
        $criteria->together = true;
        $criteria->distinct = true;

        $criteria->compare('t.name', $this->name, true);
        $criteria->compare('t.date', $this->date, true);
        $criteria->compare('genres.id', $this->assignedGenres);
        $criteria->compare('styles.id', $this->assignedStyles);
        $criteria->compare('country.id', $this->assignedCountry);

        return new CActiveDataProvider($this, array(
                'criteria' => $criteria,
                'pagination' => array(
                    'pageSize' => 10,
                ),
            ));
    }
 
связи:

Код: Выделить всё

public function relations()
    {
        return array(
            'genres' => array(self::MANY_MANY, 'Genre', 'm_artist_genres(artist_id, genre_id)', 'joinType' => 'LEFT JOIN'),
            'styles' => array(self::MANY_MANY, 'Style', 'm_artist_styles(artist_id, style_id)', 'joinType' => 'LEFT JOIN'),
            'country' => array(self::BELONGS_TO, 'Country', 'country_id', 'joinType' => 'LEFT JOIN'),
        );
    }
 
вот код из вьюхи:

Код: Выделить всё

$this->widget('zii.widgets.grid.CGridView', array(
    'id' => 'artist-grid',
    'dataProvider' => $model->search(),
    'filter' => $model,
    'ajaxUpdate' => false,
    'columns' => array(
        'date',
        'name',
        array(
            'name' => 'assignedGenres',
            'filter' => CHtml::listData(Genre::model()->findAll(array('order' => 'name ASC')), 'id', 'name'),
            'type' => 'html',
            'value' => '$data->GenreNames',
        ),
        array(
            'name' => 'assignedStyles',
            'filter' => CHtml::listData(Style::model()->findAll(array('order' => 'name ASC')), 'id', 'name'),
            'type' => 'html',
            'value' => '$data->StyleNames',
        ),
        array(
            'name' => 'assignedCountry',
            'filter' => CHtml::listData(Country::model()->findAll(array('order' => 'name ASC')), 'id', 'name'),
            'type' => 'html',
            'value' => '$data->country->name',
        ),
        array(
            'class' => 'CButtonColumn',
        ),
    ),
));
 
SQL на первой странице:

Код: Выделить всё

SELECT DISTINCT `t`.`id` AS `t0_c0`, `t`.`name` AS `t0_c1`, `t`.`lname` AS `t0_c2`, `t`.`date` AS `t0_c3`, `t`.`country_id` AS `t0_c4`, `genres`.`id` AS `t1_c0`, `genres`.`name` AS `t1_c1`, `genres`.`lname` AS `t1_c2`, `styles`.`id` AS `t2_c0`, `styles`.`name` AS `t2_c1`, `styles`.`lname` AS `t2_c2`, `styles`.`parent_id` AS `t2_c3`, `styles`.`genre_id` AS `t2_c4`, `country`.`id` AS `t3_c0`, `country`.`name` AS `t3_c1`, `country`.`lname` AS `t3_c2` FROM `m_artist` `t` LEFT JOIN	 `m_artist_genres` `genres_genres` ON (`t`.`id`=`genres_genres`.`artist_id`) LEFT JOIN	 `m_genre` `genres` ON (`genres`.`id`=`genres_genres`.`genre_id`) LEFT JOIN `m_artist_styles` `styles_styles` ON (`t`.`id`=`styles_styles`.`artist_id`) LEFT JOIN `m_style` `styles` ON (`styles`.`id`=`styles_styles`.`style_id`) LEFT JOIN `m_country` `country` ON (`t`.`country_id`=`country`.`id`) LIMIT 10
SQL на второй странице:

Код: Выделить всё

SELECT DISTINCT `t`.`id` AS `t0_c0`, `t`.`name` AS `t0_c1`, `t`.`lname` AS `t0_c2`, `t`.`date` AS `t0_c3`, `t`.`country_id` AS `t0_c4`, `genres`.`id` AS `t1_c0`, `genres`.`name` AS `t1_c1`, `genres`.`lname` AS `t1_c2`, `styles`.`id` AS `t2_c0`, `styles`.`name` AS `t2_c1`, `styles`.`lname` AS `t2_c2`, `styles`.`parent_id` AS `t2_c3`, `styles`.`genre_id` AS `t2_c4`, `country`.`id` AS `t3_c0`, `country`.`name` AS `t3_c1`, `country`.`lname` AS `t3_c2` FROM `m_artist` `t` LEFT JOIN	 `m_artist_genres` `genres_genres` ON (`t`.`id`=`genres_genres`.`artist_id`) LEFT JOIN	 `m_genre` `genres` ON (`genres`.`id`=`genres_genres`.`genre_id`) LEFT JOIN `m_artist_styles` `styles_styles` ON (`t`.`id`=`styles_styles`.`artist_id`) LEFT JOIN `m_style` `styles` ON (`styles`.`id`=`styles_styles`.`style_id`) LEFT JOIN `m_country` `country` ON (`t`.`country_id`=`country`.`id`) LIMIT 10 OFFSET 10
Данные в БД все есть, тип таблиц InnoDB, связи все проставлены и проверены...
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Постраничный вывод в CGridView

Сообщение samdark »

Как бы вы решили данную задачу в один запрос в SQL?
Аватара пользователя
Faenir
Сообщения: 292
Зарегистрирован: 2010.01.06, 01:46
Откуда: Симферополь

Re: Постраничный вывод в CGridView

Сообщение Faenir »

Ничего не получается... Видимо знаний SQL недостаточно. Это возможно вообще одним запросом реализовать? Если с together = false получать данные, то как сделать, чтобы фильтрация в CGridView по значениям из связанных по many-to-many таблиц работала?
Аватара пользователя
Faenir
Сообщения: 292
Зарегистрирован: 2010.01.06, 01:46
Откуда: Симферополь

Re: Постраничный вывод в CGridView

Сообщение Faenir »

Нашел похожую проблему здесь: http://www.yiiframework.com/forum/index ... relations/
Решения вроде как там нет...
Я понимаю, что это проблема не Yii, но все же прошу помочь.
Допустим я отключу together. Количество записей в таком случае отображается верное... но получаю такую вот ошибку:

Код: Выделить всё

CDbCommand не удалось исполнить SQL-запрос: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'genres.id' in 'where clause'. The SQL statement executed was: SELECT `t`.`id` AS `t0_c0`, `t`.`name` AS `t0_c1`, `t`.`lname` AS `t0_c2`, `t`.`date` AS `t0_c3`, `t`.`country_id` AS `t0_c4`, `country`.`id` AS `t3_c0`, `country`.`name` AS `t3_c1`, `country`.`lname` AS `t3_c2` FROM `m_artist` `t` LEFT JOIN `m_country` `country` ON (`t`.`country_id`=`country`.`id`) WHERE (genres.id=:ycp0) LIMIT 10
это при том, что в дата провайдере

Код: Выделить всё

$criteria->with = array('genres', 'styles', 'country'); 
При этом выполняется два запроса:

Код: Выделить всё

SELECT COUNT(DISTINCT `t`.`id`) FROM `m_artist` `t` LEFT JOIN `m_artist_genres` `genres_genres` ON (`t`.`id`=`genres_genres`.`artist_id`) LEFT OUTER JOIN `m_genre` `genres` ON (`genres`.`id`=`genres_genres`.`genre_id`) LEFT JOIN `m_artist_styles` `styles_styles` ON (`t`.`id`=`styles_styles`.`artist_id`) LEFT JOIN `m_style` `styles` ON (`styles`.`id`=`styles_styles`.`style_id`) LEFT OUTER JOIN `m_country` `country` ON (`t`.`country_id`=`country`.`id`) WHERE (genres.id=:ycp0)
и

Код: Выделить всё

SELECT `t`.`id` AS `t0_c0`, `t`.`name` AS `t0_c1`, `t`.`lname` AS `t0_c2`, `t`.`date` AS `t0_c3`, `t`.`country_id` AS `t0_c4`, `country`.`id` AS `t3_c0`, `country`.`name` AS `t3_c1`, `country`.`lname` AS `t3_c2` FROM `m_artist` `t` LEFT OUTER JOIN `m_country` `country` ON (`t`.`country_id`=`country`.`id`) WHERE (genres.id=:ycp0) LIMIT 10
Как сделать, чтобы фильтрация работала?
Помогите пожалуйста с решением.
Зациклился на этом, уже неделю разбираюсь...
Аватара пользователя
Neuromance
Сообщения: 716
Зарегистрирован: 2011.09.06, 13:04

Re: Постраничный вывод в CGridView

Сообщение Neuromance »

Непрочитанное сообщение MrArthur » 2011.11.17, 09:29
yiijeka » 2014.02.07, 11:32

некротемы поднимаете?))
Аватара пользователя
yiijeka
Сообщения: 3103
Зарегистрирован: 2012.01.28, 09:14
Откуда: Беларусь
Контактная информация:

Re: Постраничный вывод в CGridView

Сообщение yiijeka »

Нет, просто я в другом ответе на эту тему ссылался, и для полноты картины, добавил тут ссылку-решение.
Ответить