Использование jqGrid вместе с Yii фреймворком

Владимир | | Ajax, JavaScript, PHP, Web разработка, Yii.

yii php jqgrid

Приветствую всех!

В этой статье речь пойдёт о том как использовать Yii PHP framework и плагин к jQuery под названием jqGrid. Я не буду повторяться и рассказывать о том, что из себя представляют Yii и jqGrid и зачем они нужны. Вы легко найдёте все мои заметки на эту тему с помощью поиска по блогу 😉 (кстати, все статьи о Yii вынесены в отдельный раздел).

Когда я проводил этот эксперимент, меня интересовали два момента:

1) подключение jgGrid;

2) преобразование данных, полученных с помощью CActiveDataProvider в формат понятный для jgGrid.

С первым пунктом всё более-менее понятно. jqGrid представляет собой набор JS и CSS файлов, которые нужно подключить к странице.

Для этих целей в Yii предусмотрены специальные методы: registerScriptFile и registerCssFile. Можно, конечно, просто прописать теги script в представлении, но делать этого не рекомендуется, т.к. в этом случае фреймоворк не сможет отслеживать повторные подключения скриптов.

Примечание. Подробнее о работе с JS и CSS файлами можно почитать здесь.

Т.к. я просто экспериментировал, я сделал тестовое представление (testjqgrid.php)

//подключение CSS файлов и JS скриптов
$cs = Yii::app()->clientScript;

$cs->registerCssFile(Yii::app()->request->baseUrl.'/jqgrid/css/ui.jqgrid.css');
$cs->registerCssFile(Yii::app()->request->baseUrl.'/jqgrid/css/ui-lightness/jquery-ui-1.7.2.custom.css');

$cs->registerScriptFile(Yii::app()->request->baseUrl.'/jqgrid/js/jquery-1.3.2.min.js');
$cs->registerScriptFile(Yii::app()->request->baseUrl.'/jqgrid/js/i18n/grid.locale-ru.js');
$cs->registerScriptFile(Yii::app()->request->baseUrl.'/jqgrid/js/jquery.jqGrid.min.js');
?>
<table id="list"></table> 
<div id="pager"></div> 

<script type="text/javascript">
$(function() {
	jQuery("#list").jqGrid( {
		url : '<?php echo $this->createUrl('blogs/jqgriddata'); ?>',
		datatype : 'json',
		mtype : 'GET',
		colNames : [ '#', 'Name', 'URL', 'API' ],
		colModel : [ {
			name : 'b_id',
			index : 'b_id',
			width : 60
		}, {
			name : 'b_name',
			index : 'b_name',
			width : 120
		}, {
			name : 'b_url',
			index : 'b_url',
			width : 150,
			align : 'right'
		}, {
			name : 'b_api',
			index : 'b_api',
			width : 80,
			align : 'right'
		} ],
		pager : '#pager',
		rowNum : 10,
		rowList : [ 10, 20, 30 ],
		sortname : 'invid',
		sortorder : 'desc',
		viewrecords : true,
		caption : 'Blogs'
	});
});
</script>

Как видите, сначала мы регистрируем скрипты и файлы стилей, затем вставляем тег для таблицы (строка 12) и тег для панели навигации.

Примечание. В этом примере использован первый попавшийся контроллер (BlogsController). Кроме того, для получения данных используется модель Blogs. Зачем она нужна, в данном случае не принципиально, мы просто будем отображать записи из таблицы с помощью jqGrid.

В конце представления находится код настройки jqGrid. Таблица будет содержать 4 колонки с названиями: «#», «Name», «URL» и «API», а соответствующие поля в таблице имеют названия: «b_id», «b_name», «b_url» и «b_api».

И, конечно, нужно указать адрес скрипта, который будет формировать данные для таблицы (строка 18, параметр url).

Формирование таблицы.

Т.к. jqGrid получает данные с помощью AJAX запросов, то мы добавим два метода в контроллер. Первый – actionJqgrid, будет формировать страницу с таблицей, т.е. просто загружать представление. Второй – actionJqgriddata, предназначен для обработки AJAX запросов.

public function actionJqgrid() {
	$this->render('testjqgrid');
}

public function actionJqgriddata() {
	$dataProvider=new CActiveDataProvider('Blogs', array(
		'pagination'=>array(
			'pageSize'=>$_GET['rows'],
			'currentPage'=>$_GET['page']-1,
		),
	));
	$responce->page = $_GET['page'];
	$responce->records = $dataProvider->getTotalItemCount();
	$responce->total = ceil($responce->records / $_GET['rows']);
	$rows = $dataProvider->getData();
	foreach ($rows as $i=>$row) {
		$responce->rows[$i]['id'] = $row['b_id'];
		$responce->rows[$i]['cell'] = array($row->b_id, $row->b_name, $row->b_url, $row->b_api);
	}
	echo json_encode($responce);
}

Рассмотрим их подробнее. Как я уже говорил, метод actionJqgrid просто загружает представление. Получать данные из базы нам не нужно, т.к. при создании таблицы jqGrid всё равно отправит AJAX запрос на их получение.

С методом actionJqgriddata ситуация немного сложнее. Дело в том, что нам нужно преобразовать данные, которые возвращает CActiveDataProvider в формат, понятный jqGrid.

Для этого мы создаём объект $responce и в нём сохраняем:

1) page – номер текущей страницы;

2) records – общее количество записей;

3) total – общее количество страниц;

4) rows – массив с данными. Каждый элемент этого массива должен содержать id текущей записи и массив cell с данными ячеек. Этот массив мы формируем с помощью цикла (строки 16-19).

После это преобразовываем $responce в JSON формат и возвращаем браузеру.

Как видите, принцип достаточно простой, но код получается объёмный. В принципе, есть расширение eziiui, которое упрощает работу с jqGrid, но судя по отзывам, оно ограничивает ваши возможности в использовании jqGrid, поэтому я им не пользовался.

Может быть стоит написать расширение, которое будет преобразовывать данные из CActiveDataProvider в JSON формат? Или есть другие идеи?

Полезные ссылки

Блоггер, заходи на новый форум блоггеров, общайся и зарабатывай.

Не бойтесь холода, подберите себе шарфы интернет магазин.

  • Michael

    А вот как сделать так, что бы заработала сортировка по колонкам?

    • Добавить в CActiveDataProvider (строка 6 в втором листинге) элемент sort и в его параметрах указать настройки сортировки. Параметры jqGrid отправит в $_GET массиве.

  • Michael

    А вот как сделать так, что бы заработала сортировка по колонкам?

    • Добавить в CActiveDataProvider (строка 6 в втором листинге) элемент sort и в его параметрах указать настройки сортировки. Параметры jqGrid отправит в $_GET массиве.

  • pauldee

    Не понял какому классу принадлежит объект $responce

  • pauldee

    Не понял какому классу принадлежит объект $responce

  • andrey

    Владимир, а как можно задать подсказку для заголовка? Все название не вмещается и я его сократил, хочу чтобы в хинте было полное название. Как это можно релизовать?

  • andrey

    Владимир, а как можно задать подсказку для заголовка? Все название не вмещается и я его сократил, хочу чтобы в хинте было полное название. Как это можно релизовать?

  • andrey

    Спасибо, буду пробовать. По-моему как раз то что нужно. Потом отпишусь о результате

  • andrey

    Спасибо, буду пробовать. По-моему как раз то что нужно. Потом отпишусь о результате

  • Владимир, а как добавить больше функциональности? (данный вариант годится только для отображения) Например, добавление, удаление и прочее??? С оф. сайта пробовал, не получилось, может у Вас есть решение полегче?

  • Читал, пробовал ))) Но все же не совсем то, ибо с Yii получилось только отображение из БД получить, ну да ладно, буду дальше пробовать.

  • В Yii вам нужно создать метод в контроллере, который будет вставлять
    записи. Код метода, такой же как и у отдельного скрипта, только
    библиотека для работы с БД используется другая.
    После этого, проверяйте, куда jqGrid отправляет запросы и с какими данными.

  • alexy4b

    Не понял( что за класс и в каком месте создаётся объект??

  • stdClass — родовой (общий, generic) php класс. Используется для анонимных объектов, динамических свойств и т.п. Создается автоматически. В данном случае — при вызове
    $responce->page = …

  • BuCeFaL

    Владимир , отлично пишите !
    Спасибо =)
    недавно сам тулил в Yii jqGrid.
    Ваша реализация понравилась намного больше ))

  • Mgs3bg

    А вот как сделать так, что бы заработал jQuery(«#list»).jqGrid('filterToolbar', {stringResult: true, searchOnEnter: false, defaultSearch : «cn»});
    что нада добавит в CActiveDataProvider.
    для сортировка заработат вот:
    public function actionJqgriddata() {
        $sidx = $_GET['sidx']; // get index row — i.e. user click to sort
        $sord = $_GET['sord']; // get the direction
       
            $dataProvider=new CActiveDataProvider('Delme', array(
                'pagination'=>array(
                    'pageSize'=>$_GET['rows'],
                    'currentPage'=>$_GET['page']-1,
                ),
                'sort'=>array(
                'defaultOrder'=>»$sidx $sord»
            )
           
           
           
           
            ));
    pls помогите, спосибо!

    • Т.е. вы хотите реализовать поиск?
      По-умолчанию CActiveDataProvider вызывает метод findAll, который возвращает все записи под ряд. Вам нужно вызвать метод setCriteria и передать ему объект CDbCriteria, а в нём указать параметры поиска.

  • Парни, подскажите, пожалуйста, по сортировке в jqGrid — есть столбец «Num» (например), как данные отсортировать так, чтобы сначала шли строки со значением 1,2,3,…20..50, а потом строки с пустым значением NUM. Сейчас, просто напросто, если установить сортировку в ASC сначала идут записи с пустыми ячейками, а потом только с номера от 1 и далее. Спасибо заранее.

    • У меня есть статья по сортировке — попробуйте использовать пример с сортировкой числового поля по правилам текстового.
      Результат не гарантирую 🙂
      Возможно, будет проще и быстрее вытянуть данные двумя запросами.

  • Марк

    Владимир, добрый день! Спасибо за статью. У меня получилось поключить jqgrid к yii. Но проблема в том, что хочется сделать jqgrid частью формы. Чтобы была форма, например счет. Вначале пользователь в обычной форме yii воодит данные клиента и тд, а потом в той же форме в виде jqgrid вводит перечень товаров и услуг за что выписывается счет. В конце нажимает общий сабмит и контроллер должен получить все данные — от стандартно форсы yii и список записей из jqgrid-a. Как это сделать? ак в controller передать надор записей вместе с основной формой? Спасибо.

    • Для такой задачи использовать jqGrid — не самое удачное решение. Т.е. использовать его вы сможете, но для того, чтобы форма работала по описанному вами сценарию, придётся отключить часть возможностей jqGrid. Например, по-умолчанию, jqGrid при добавлении записи, отправит ajax запрос на сервер, чтобы её сохранить. Но в вашем случае этого делать нельзя, т.к. эти данные должны быть отправлены вместе с основной формой. Поэтому получается, что jqGrid вы будете использовать как обычную таблицу. Поэтому гораздо проще решить вашу задачу с помощью, например, jQuery и html таблицы. Кроме того, страница будет быстрее загружаться.