Сортировка в CGridView при произвольном SQL запросе

Итак, мы вывели и модифицировали результат нашего запроса в таблицу с помощью CGridView компонента Zii виджета, теперь было бы здорово не меняя самого запроса научиться сортировать полученную информацию просто кликнув на заголовок столбца. В этом нам поможет класс CSort и параметр массива CSqlDataProvider sort, но обо всем подробнее.

Итак, начало нашего кода уже довольно стандартное:

$sql = "select * from test_table";
$rows = Yii::app()->db->createCommand($sql)->queryAll();
$count = count($rows);

Объявляем класс CSort:

$sort = new CSort();

И вызываем потомков этого класса:

$sort->attributes = array(
'id' => array(
    'id' => array(
        'asc' => 'test_table.id asc',
        'desc' => 'test_table.id desc',
    ),
    'Имя' => array(
        'asc' => 'test_table.first_name asc',
        'desc' => 'test_table.first_name desc',
    ),
    'Фамилия' => array(
        'asc' => 'test_table.second_name asc',
        'desc' => 'test_table.second_name desc',
    ),
);

В результате получаем массив параметров нужных для сортировки по столбцу id, Имя, Фамилия, можно было бы вместо test_table.имя_столбца написать просто имя_столбца, так как у нас запрос данных из одной таблицы. Обратите внимание что первое id это id из keyField CSqlDataProvider. Теперь немного модифицируем код $SqldataProvider дабы вставить туда наши параметры сортировки:

$SqldataProvider = new CSqlDataProvider($sql, array(
    'keyField'=>'id',
    'totalItemCount'=>$count,
    'pagination'=>array(
        'pageSize'=>100,
    ),
    'sort'=>$sort,
));

И, конечно, сам вывод данных в виджет:

$this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider'=>$SqldataProvider,
    'enablePagination' => true,
    'columns'=>array(
        array(
            'name' => 'id',
            'value' => 'CHtml::encode($data["id"])',
            'type' => 'raw',
        ),
        array(
            'name' => 'Имя',
            'value' => 'CHtml::encode($data["first_name"])',
            'type' => 'text',
        ),
        array(
            'name' => 'Фамилия',
            'value' => 'CHtml::encode($data["second_name"])',
            'type' => 'text',
        ),
    ),
));

На этом можно было бы заканчивать и приводить полный листинг кода, который достаточно просто засунуть в ваше представление и оно оживет, вот только получившийся код уже не маленький и правильнее его уже делить в соответствии с MVC подходом. Для этого в папке models создаем php файл следующего содержания:

<?php
class test
{
    public function get_testtablet_dataProvider() {
        $sql = "select * from test_table";
        $rows = Yii::app()->db->createCommand($sql)->queryAll();
        $count = count($rows);
        $sort = new CSort();
        $sort->attributes = array(
                'id' => array(
                    'asc' => 'test_table.id asc',
                    'desc' => 'test_table.id desc',
                ),
                'Имя' => array(
                    'asc' => 'test_table.first_name asc',
                    'desc' => 'test_table.first_name desc',
                ),
                'Фамилия' => array(
                    'asc' => 'test_table.second_name asc',
                    'desc' => 'test_table.second_name desc',
                ),
            );
        $SqldataProvider = new CSqlDataProvider($sql, array(
            'keyField'=>'id',
            'totalItemCount'=>$count,
            'pagination'=>array(
                'pageSize'=>100,
            ),
            'sort'=>$sort,
        ));
        return $SqldataProvider;
    }
}
?>

И сохраняем его с именем test.php, в целом это и будет наша модель данных, теперь ее нужно вызвать из представления и в переменную записать результат выполнения функции get_testtablet_dataProvider, делается это так:

$dd = New test;
$SqldataProvider = $dd->get_testtablet_dataProvider();

Остается только добавить код вывода данных из виджета о котором говорилось чуть выше. В результате у вас должно получится что-то похожее на это:

sort table

comments powered by HyperComments
Max
2014-10-28 14:20:47
$sql = "select * from test_table"; $rows = Yii::app()->db->createCommand($sql)->queryAll(); $count = count($rows); Так делать нельзя! Эта строка будет выгружать все записи из таблицы!!! А если в таблице миллион строк? Нужно обязательно использовать Mysql функцию COUNT для подсчета кол-ва строк.: $sql = "select count(*) from test_table"; $count=Yii::app()->db->createCommand($sql)->queryScalar();
Алексей
2014-10-29 21:24:55
полностью согласен, но на тот момент мне это казалось вполне хорошим вариантом
При копировании материалов обратная ссылка на play-stop.ru желательна обязательна!