Yii PHP фреймворк: оформление административных страниц

6 июля, 2010
yii grid view

Одной из наиболее мощных возможностей фреймворка Yii является генерация кода. Она позволяет сразу после создания таблицы в базе данных получить файлы модели, контроллера и представлений. Т.е. весь необходимый код для выполнения CRUD операций.

Но, естественно, код формируется по стандартному шаблону, дизайн которого вам, возможно, захочется изменить.

Взгляните на обычную страницу управления записями, сформированную с помощью компонента CGridView.

basic grid thumb

Такая страница доступна по адресу
sitename.domen?r=controller/admin

Она состоит из трех частей.

1) Строки с номерами показанных записей и их количеством (summary).

2) Таблицы с данными (items).

3) Листалки (pager). Если записей в таблице меньше, чем отображается на странице, этот элемент показан не будет.

Теперь взгляните на код, который создает такую таблицу.

<?php $this->widget('zii.widgets.grid.CGridView', array(
	'id'=>'cities-grid',
	'dataProvider'=>$model->search(),
	'filter'=>$model,
	'columns'=>array(
		'id',
		'city',
		'country',
		array(
			'class'=>'CButtonColumn',
		),
	),
)); ?>

Источником данных служит объект CActiveDataProvider, который создается в контроллере. Но сейчас речь не о данных.

Попробуем изменить порядок вывода основных элементов.

CGridView имеет параметр template, который позволяет управлять выводом основных элементов страницы. Этот параметр принимает строку, в которой нужно перечислить необходимые элементы страницы.

Например, следующий код покажет листалку сверху и снизу страницы.

<?php $this->widget('zii.widgets.grid.CGridView', array(
	…,
	'template'=>'{summary} {pager} {items} {pager}',
	'columns'=>array(
		…,
	),
)); ?>

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

Если нужно изменить дизайн, то я бы рекомендовал делать в следующей последовательности.

1) Попытаться добиться результата, не меняя разметку, с помощью CSS стилей. Разметка, которую создаёт фреймворк, достаточна простая и соответствует стандартам.

2) Если необходимо, изменить разметку.

Рассмотрим первый вариант – использование своих CSS стилей.

По-умолчанию, для оформления CGridView используются следующие CSS файлы:

1) Для оформления таблицы framework/zii/widgets/assets/gridview/styles.css (он автоматически копируется в папку DOCUMENT_ROOT/accets/номер/gridview/styles.css).

2) Для оформления листалки framework/web/widgets/pagers/pager.css (он копируется в assets/номер/pager.css).

Допустим, ваши стили находятся в файлах gridview-styles.css и pager-styles.css, которые расположены в папке DOCUMENT_ROOT/css.

Подключаем файл со стилями таблицы, для этого передаем ссылку на файл в параметре cssFile.

<?php $this->widget('zii.widgets.grid.CGridView', array(
	…,
	'cssFile'=>Yii::app()->getBaseUrl(true).'/css/admin-styles.css',
	'columns'=>array(
		…,
	),
)); ?>

В результате, фреймворк будет загружать ваш файл вместо стандартного.

Кроме того, есть несколько параметров (itemsCssClass, rowCssClass, summaryCssClass и др.), которые позволяют указать ваши имена CSS классов. Но, вы можете использовать и стандартные имена классов, например, взять стандартный файл со стилями и переделывать его под свой дизайн.

Установка стилей для листалки (pager) немного отличается.

Из CGridView нужно получить доступ к атрибуту pager и устанавливать параметры для него.

<?php $this->widget('zii.widgets.grid.CGridView', array(
	…,
	'pager'=>array('cssFile'=>Yii::app()->getBaseUrl(true).'/css/pager-styles.css'),	'columns'=>array(
		…,
	),
)); ?>

Код похожий, но параметр cssFile передается в массиве и присваивается атрибуту pager.

Тут возникает интересный вопрос: «Какие еще параметры мы можем передать в этом массиве?»

Любые атрибуты класса CBasePager, а также его потомков, в том числе и имя класса-потомка, который используется для создания листалки.

В дистрибутив входит два таких класса CLinkPager (создает список ссылок с номерами страниц, используется по-умолчанию) и CListPager (создает выпадающий список с номерами страниц).

Заменить CLinkPager на CListPager можно так.

…
	'pager'=>array('class'=>'CListPager'),
…

Тут мы подходим к вопросу изменения разметки.

Допустим, нам нужно создать листалку в которой элементы страниц будут находиться внутри тегов span, а не li, как выводит CLinkPager.

Можно, конечно, создать класс, производный от CBasePager, но в данном случае будет удобнее наследовать CLinkPager.

У меня получился такой код (файл protected/components /SpanLinkPager.php).

class SpanLinkPager extends CLinkPager {

	public function run()
	{
		$buttons=$this->createPageButtons();
		if(empty($buttons))
			return;
		$this->registerClientScript();
		echo $this->header;
		echo CHtml::tag('div',$this->htmlOptions,implode("\n",$buttons));
		echo $this->footer;
	}

	protected function createPageButton($label,$page,$class,$hidden,$selected)
	{
		if($hidden || $selected)
			$class.=' '.($hidden ? self::CSS_HIDDEN_PAGE : self::CSS_SELECTED_PAGE);
		return '<span class="'.$class.'">'.CHtml::link($label,$this->createPageUrl($page)).'</span>';
	}
}

Я просто нашел в CLinkPager методы, в который формируется разметка и переопределил их. Т.е. код остался тот же, просто ul заменил на div (строка 12), а li – на span (строка 20).

Используя такой же подход можно переопределить класс CGridView и изменить разметку необходимым вам образом. Вот список основных методов, которые формируют разметку CGridView:
renderItems
renderTableHeader
renderTableFooter
renderTableBody
renderEmptyText
renderFilter
renderTableRow
renderSummary
(находится в CBaseListView, который является предком CGridView)

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

Если у вас возникли вопросы или есть замечания, пишите, постараюсь ответить.

До встречи!

Понравилась статья? Подписывайтесь на продолжение rss link !

Или на мой твиттер twitter link

]]>

Добавьте эту страницу в google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru

]]>

Опубликовано в HTML, PHP, Web разработка, Yii Комментарии (20) »

]]>

Вы можете оставить комментарий. Трекбеки закрыты.

  • Betaboy

    Yii рулит! )

  • http://www.boots-stores.us uggs outlet

    Agree with Landlord sit.Various of online games provided are dynamic sense and free indefinitely.We are looking forward to you to here share the experience of
    exciting game competition! Dior homme shoes

  • BuCeFaL

    +1 )

  • SpongeBolt

    Спасибо большое!

  • sergi

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

  • http://www.simplecoding.org Владимир

    Очень просто – никак :)
    Верстальщик на основе макета (psd) делает html страницу с нужной разметкой и css стилями. Если эта разметка совпадает с разметкой, которую создает CGridView (или ее можно безболезненно изменить так чтобы она совпадала), то использует стандартный компонент.
    В противном случае – программист должен переопределить класс.
    Естественно, очень желательно предварительно показать верстальщику стандартную разметку. В большинстве случаев всё решается с помощью css.

    • Sentox

      То есть верстальщик должен быть на порядок выше по специальности чем при обычных шаблонах?

      • http://www.simplecoding.org Владимир

        Нет, почему выше?
        В любых шаблонах есть вставки кода в которых верстальщик должен ориентироваться.

  • Игорь

    Подскажите, пожалуйста, а как можно изменить название заголовков? Вместо ID, COUNTRY № и Страна

  • http://www.simplecoding.org Владимир

    Эти изменения нужно вносить в модели (models/Countries.php).
    Там есть метод
    public function attributeLabels()
    {
    return array(
    'id' => '#',
    'name' => 'Страна',
    );
    }
    Ключи элементов массива будут соответствовать названиям полей в таблице.

  • Игорь

    Спасибо за ваши ответы, помогло)

  • Professor

    Только начал изучать Yii, как хорошо что наткнулся на ваш блог =)
    Интересует вопрос, а как изменить текст summary?

    • Professor

      И текст листалки тоже хотелось бы поменять.

      • http://www.simplecoding.org Владимир

        Используйте описанный в этой статье метод (второй вариант, где рассказывается об изменении разметки). Только для summary вам нужен метод CBaseListView.renderSummary.
        Переопределите его и можете выводить все, что угодно.

        Но если нужно изменить только текст, можно не переопределять метод.
        Используйте свойство
        summaryText

        • Professor

          Спасибо большое, разобрался =)

  • Arbuscula

    А если я хочу добавить еще один блок окромя {summary} {items} {pager}, например, {export}. Я так понял мне нужно переопределить CGridView и описать метод renderExport ?
    И еще вопрос, когда я переопределю класс CGridView. class MyGridView extends CGridView{…} Как он найдет класс CGridView от которого я наследую? Ведь он вызывался путем zii.widget.grid.CGridView.

    • Arbuscula

      Я написал в файле MyGridView прям перед определением класса строку: Yii::import('zii.widgets.grid.CGridView'); Правильно ли это ? Или нужно в main.php это прописывать ?

      • http://www.simplecoding.org Владимир

        Вроде все правильно.
        Шаблоны {summary}, {items} и т.п. создаются с помощью renderSection(), который в свою очередь вызывает renderимя_шаблона (возможно, export нужно написать с маленькой буквы, не проверял).

        У вас появляются какие-нибудь ошибки при запуске кода?

  • Елена Сапрыгина

    Подскажите как просмотреть ячейку из бд, не нажатием стандартной кнопки, а нажатием на саму строчку, id или name

    • http://www.simplecoding.org Владимир

      Я не совсем понимаю проблему. Повторил ваш код на тестовой установке yii. Ссылки нормально создались.

          'columns'=>array(
              'id',
              array(
                  'label'=>'test',
                  'header'=>'Name',
                  'urlExpression' => 'array("/tblUser/view", "id" => $data->id)',
                  'class'=>'CLinkColumn',
              ),
              'username',
              'password',
              'email',
              array(
                  'class'=>'CButtonColumn',
              ),
          ),

]]>
Tweet