Простейшая админка
Итак, у нас есть отображение новостей из базы данных, и теперь мы хотим организовать их редактирование (а также добавление, удаление) в админке.
Очевидно, что для этого в нашем компоненте "Новости" необходимо создать еще один контроллер, который умеет все это делать. На первый взгляд это может показаться весьма нетривиальной задачей, но на самом деле в 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; } }
Теперь при создании новой записи текущая дата будет подставляться автоматически.
Итог
Посмотреть полный код полученного компонента можно по этой ссылке.