Простейшая админка

Итак, у нас есть отображение новостей из базы данных, и теперь мы хотим организовать их редактирование (а также добавление, удаление) в админке.

Очевидно, что для этого в нашем компоненте "Новости" необходимо создать еще один контроллер, который умеет все это делать. На первый взгляд это может показаться весьма нетривиальной задачей, но на самом деле в TAO существует для этого уже готовый механизм в виде базового контроллера CMS.Controller.Table, от которого следует наследовать свой контроллер, в котором указать информацию о том, что редактировать и каким образом.

Создаем контроллер

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

Создадим PHP-файл app/components/News/Admin.php:

<?php

Core::load('CMS.Controller.Table');

class Component_News_Admin extends CMS_Controller_Table
{
	protected $orm_name = 'news';
	protected $title_list = 'Новости';
	protected $title_edit = 'Редактирование новости';
	protected $title_add = 'Добавление новости';
	protected $norows = 'Новостей нет';
	protected $button_add = 'Добавить новость';

	protected function list_fields()
	{
		return array(
			'idate' => array(
				'type' => 'datestr',
				'caption' => 'Дата',
			),
			'title' => array(
				'caption' => 'Заголовок',
			),
		);
	}

	protected function form_tabs()
	{
		return array(
			'default' => 'Свойства',
			'content' => 'Текст новости',
		);
	}

	protected function form_fields()
	{
		return array(
			'idate' => array(
				'type' => 'datestr',
				'caption' => 'Дата',
				'tab' => 'default',
				'datepicker' => true,
			),
			'title' => array(
				'caption' => 'Заголовок',
				'tab' => 'default',
				'style' => 'width:100%',
			),
			'announce' => array(
				'type' => 'textarea',
				'caption' => 'Краткий текст',
				'tab' => 'default',
				'style' => 'width:100%;height:200px',
			),
			'content' => array(
				'type' => 'textarea',
				'tab' => 'content',
				'style' => 'width:100%;height:400px',
			),
		);
	}

}

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

$orm_name

Это мнемоническое имя ORM-маппера для той таблицы, которую мы собираемся администрировать.

$title_list

Заголовок страницы списка записей.

$title_edit

Заголовок страницы с формой редактирования существующей записи.

$title_add

Заголовок страницы с формой добавления новой записи.

$norows

Текст сообщения, выводящегося вместо списка записей в случае если не найдено ни одной записи.

$button_add

Текст на кнопке перехода на форму добавления. Эта кнопка выводится на странице списка записей справа вверху.

list_fields()

Эта функция возвращает информацию о том, что и как выводить на списке записей. Формат информации - в виде массива, ключами которого являются имена полей, а значениями - в свою очередь массивы. Там обязательным порядком указываем caption - заголовок колонки. В некоторых случаях можно указать тип поля (type) - в данном случае мы указали для даты тип datestr для того, чтобы дата выводилась не как UNIX TIMESTAMP, а в удобочитаемом виде.

form_tabs()

Эта функция возвращает список вкладок формы редактирования/добавления. Можно обойтись и без этой функции - в этом случае форма будет без вкладок, и все поля будут идти одним длинным списком. Однако в нашем случае есть поле content (полный текст новости), которое на форме занимает довольно обширное место, поэтому для этого поля мы создадим отдельную вкладку.

form_fields()

Здесь мы управляем формой редактирования/добавления. Формат аналогичен функции list_fields, только инфомации о полях немного больше. Некоторые пояснения:

  • Те поля, для которых не указан параметр type, редактируются как обычные строковые поля.
  • Для многовкладочных форм обязателен параметр tab, в котором указано в какой вкладке будет находиться поле. Если этот параметр опустить, то поле вообще не будет отображено в форме.
  • Параметр caption для поля content мы опустили, поскольку это единственное поле на вкладке, и вполне достаточно заголовка вкладки.
  • У поля idate есть параметр datepicker, означающий, что рядом с полем нужно показать кнопку для визуального выбора даты. Вообще, для разных типов полей могут существовать специальные, присущие только им параметры.
  • Для многих полей мы указываем параметр style, который по сути является HTML-тегом для поля формы. Таким способом мы здесь определяем видимые размеры полей в форме.

Модифицируем роутер

Создать контроллер - мало, поскольку система о нем ничего не знает. Теперь нам нужно добавить в роутер информацию о контроллере:

public function controllers()
{
	return array(
		'Component.News.Controller' => array(
			'path' => '/news/',
			'rules' => array(
				'{^$}' => array('action' => 'view_list'),
				'{^(\d+)/$}' => array('{1}','action' => 'view_item'),
			),
		),
		'Component.News.Admin' => array(
			'path' => '/admin/news/',
			'table-admin' => true,
		),
	);
}

В массив, возвращаемый функцией controllers роутера, добавился новый элемент, касающийся созданного нами контроллера Component.News.Admin. Особенность этого элемента в том, что в нем нет раздела rules. Вместо него установлен параметр table-admin, который означает, что правила маршрутизации следует взять стандартные для табличного контроллера.

Вот теперь админка новостей готова к работе. Зайдите по адресу /admin/news/ и убедитесь в этом сами.

Значения полей по умолчанию

Вы наверняка попробовали добавить новость и увидели что в форме добавления поле "Дата" - пустое. И, конечно же, у вас возник закономерный вопрос: а нельзя ли, чтобы при добавлении новости сюда автоматически подставлялась текущая дата? Разумеется, можно. Для этого нужно при создании нового объекта (в данном случае новости) присвоить значения по умолчанию. Это делается в функции setup ORM-объекта (класса, наследуемого от CMS_ORM_Entity).

Класс Component_News_DB_Item (в модуле Component.News.DB), который до сих пор у нас был пустым, теперь обзаводится методом setup():

class Component_News_DB_Item extends CMS_ORM_Entity
{
	public function setup()
	{
		// Не забываем вызвать setup у родительского класса
		parent::setup();

		// Устанавливаем текущую дату
		$this['idate'] = time();

		// Обязательно нужно вернуть $this
		return $this;
	}
}

Теперь при создании новой записи текущая дата будет подставляться автоматически.

Итог

Посмотреть полный код полученного компонента можно по этой ссылке.

17.01.2014
Все статьи