Часть 10 - конфигурация и параметры
Добавление конфигурационных параметров
Фреймворк Joomla позволяет использовать параметры, сохраненные для каждого компонента. Создайте конфигурационный файл admin/config.xml со следующим кодом:
<?xml version="1.0" encoding="utf-8"?> <config> <fieldset name="greetings" label="COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_LABEL" description="COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_DESC" > <field name="show_category" type="radio" label="COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_LABEL" description="COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_DESC" default="0" > <option value="0">JHIDE</option> <option value="1">JSHOW</option> </field> </fieldset> </config>
Этот файл будет прочитан встроенным в Joomla компонентом com_config. На данный момент мы определили всего один параметр show_category
- отображать или не отображать название категории в публичной части сайта.
Самым лучшим способом для установки параметров будет добавление кнопки "Настройки" на панель инструментов. Для этого необходимо внести изменения в метод addToolBar()
в файле admin/views/helloworlds/view.html.php:
/** * Устанавливает панель инструментов. * * @return void */ protected function addToolBar() { JToolBarHelper::title(JText::_('COM_HELLOWORLD_MANAGER_HELLOWORLDS'), 'helloworld'); JToolBarHelper::addNew('helloworld.add'); JToolBarHelper::editList('helloworld.edit'); JToolBarHelper::divider(); JToolBarHelper::deleteList('', 'helloworlds.delete'); JToolBarHelper::divider(); JToolBarHelper::preferences('com_helloworld'); } }
Кнопка выводится с помощью JToolBarHelper::preferences('com_helloworld')
.
Использование конфигурационных параметров в качестве значения по умолчанию
Теперь определим этот параметр индивидуально для каждого сообщения. Вносим изменения в файл admin/models/forms/helloworld.xml:
<?xml version="1.0" encoding="utf-8"?> <form addrulepath="/administrator/components/com_helloworld/models/rules" > <fieldset name="details"> <field name="id" type="hidden" /> <field name="greeting" type="text" label="COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_LABEL" description="COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_DESC" size="40" class="inputbox validate-greeting" validate="greeting" required="true" default="" /> <field name="catid" type="category" extension="com_helloworld" class="inputbox" default="" label="COM_HELLOWORLD_HELLOWORLD_FIELD_CATID_LABEL" description="COM_HELLOWORLD_HELLOWORLD_FIELD_CATID_DESC" required="true" > <option value="0">JOPTION_SELECT_CATEGORY</option> </field> </fieldset> <fields name="params"> <fieldset name="params" label="JGLOBAL_FIELDSET_DISPLAY_OPTIONS" > <field name="show_category" type="list" label="COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_LABEL" description="COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_DESC" default="" > <option value="">JGLOBAL_USE_GLOBAL</option> <option value="0">JHIDE</option> <option value="1">JSHOW</option> </field> </fieldset> </fields> </form>
Мы определили одинаковый параметр show_category
для каждого сообщения с помощью дополнительного значения: По умолчанию. Это значение устанавливается в общем файле конфигурации config.xml.
Для хранения параметров необходимо добавить в таблицу базы данных еще одну колонку params
. Откройте файл admin/sql/install.mysql.utf8.sql и замените в нем код на следующий:
DROP TABLE IF EXISTS `#__helloworld`; CREATE TABLE `#__helloworld` ( `id` int(11) NOT NULL AUTO_INCREMENT, `greeting` varchar(25) NOT NULL, `catid` int(11) NOT NULL DEFAULT '0', `params` TEXT NOT NULL DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8; INSERT INTO `#__helloworld` (`greeting`) VALUES ('Hello World!'), ('Good bye World!');
Не забываем про обновление компонента и изменяем файл admin/sql/updates/mysql/0.0.10.sql:
ALTER TABLE `#__helloworld` ADD `params` TEXT NOT NULL DEFAULT '';
Для поддержки параметров необходимо внести изменения и в класс таблицы HelloWorldTableHelloWorld
. В базе данных параметры будут храниться в формате JSON и загружаться в JRegistry. Нам необходимо переопределить JTable
методы bind и load и добавить их в admin/tables/helloworld.php:
<?php // Запрет прямого доступа. defined('_JEXEC') or die; // Подключаем библиотеку таблиц Joomla. jimport('joomla.database.table'); /** * Класс таблицы HelloWorld. */ class HelloWorldTableHelloWorld extends JTable { /** * Конструктор. * * @param JDatabase &$db Коннектор объекта базы данных. */ public function __construct(&$db) { parent::__construct('#__helloworld', 'id', $db); } /** * Переопределяем bind метод JTable. * * @param array $array Массив значений. * @param array $ignore Массив значений, которые должны быть игнорированы. * * @return boolean True если все прошло успешно, в противном случае false. */ public function bind($array, $ignore = array()) { if (isset($array['params']) && is_array($array['params'])) { // Конвертируем поле параметров в JSON строку. $parameter = new JRegistry; $parameter->loadArray($array['params']); $array['params'] = (string) $parameter; } return parent::bind($array, $ignore); } /** * Переопределяем load метод JTable. * * @param int $pk Первичный ключ. * @param boolean $reset Сбрасывать данные перед загрузкой или нет. * * @return boolean True если все прошло успешно, в противном случае false. */ public function load($pk = null, $reset = true) { if (parent::load($pk, $reset)) { // Конвертируем поле параметров в регистр. $params = new JRegistry; $params->loadString($this->params); $this->params = $params; return true; } else { return false; } } }
Изменяем интерфейс администратора
Режим редактирования сообщения должен показывать выбор параметров администратору. Для этого отредактируем файл admin/views/helloworld/tmpl/edit.php:
<?php // Запрет прямого доступа. defined('_JEXEC') or die; // Загружаем тултипы. JHtml::_('behavior.tooltip'); // Загружаем проверку формы. JHtml::_('behavior.formvalidation'); // Получаем параметры из формы. $params = $this->form->getFieldsets('params'); ?> <form action="<?php echo JRoute::_('index.php?option=com_helloworld&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="helloworld-form"> <div> <fieldset> <legend><?php echo JText::_('COM_HELLOWORLD_HELLOWORLD_DETAILS'); ?></legend> <ul> <?php foreach ($this->form->getFieldset('details') as $field) : ?> <li><?php echo $field->label; echo $field->input; ?></li> <?php endforeach; ?> </ul> </fieldset> </div> <div> <?php echo JHtml::_('sliders.start', 'helloworld-slider'); foreach ($params as $name => $fieldset): echo JHtml::_('sliders.panel', JText::_($fieldset->label), $name.'-params'); if (isset($fieldset->description) && trim($fieldset->description)) : ?> <p><?php echo $this->escape(JText::_($fieldset->description));?></p> <?php endif;?> <fieldset > <ul> <?php foreach ($this->form->getFieldset($name) as $field) : ?> <li><?php echo $field->label; ?><?php echo $field->input; ?></li> <?php endforeach; ?> </ul> </fieldset> <?php endforeach; ?> <?php echo JHtml::_('sliders.end'); ?> </div> <div> <input type="hidden" name="task" value="" /> <?php echo JHtml::_('form.token'); ?> </div> </form>
Здесь мы добавили слайдеры с помощью JHtml
и панель, в которой будут отображаться наши параметры.
Изменяем публичную часть
Необходимо также отредактировать публичную часть для того, чтобы был учтен новый параметр show_category
. Для этого изменим модель:
- она должна объединять глобальные параметры и индивидуальные параметры
- она должна предоставлять категорию
Откройте файл site/models/helloworld.php и замените код на следующий:
<?php // Запрет прямого доступа. defined('_JEXEC') or die; // Подключаем библиотеку modelitem Joomla. jimport('joomla.application.component.modelitem'); /** * Модель сообщения компонента HelloWorld. */ class HelloWorldModelHelloWorld extends JModelItem { /** * Получаем сообщение. * * @param int $id Id сообщения. * * @return object Объект сообщения, которое отображается пользователю. * * @throws Exception Если сообщение не найдено. * */ public function getItem($id = null) { // Если id не установлено, то получаем его из состояния. $id = (!empty($id)) ? $id : (int) $this->getState('message.id'); if ($this->_item === null) { $this->_item = array(); } if (!isset($this->_item[$id])) { // Конструируем SQL запрос. $query = $this->_db->getQuery(true); $query->select('h.greeting, h.params') ->from('#__helloworld as h') ->select('c.title as category') ->leftJoin('#__categories as c ON c.id = h.catid') ->where('h.id = ' . (int) $id); $this->_db->setQuery($query); $data = $this->_db->loadObject(); // Генерируем исключение, если сообщение не найдено. if (empty($data)) { throw new Exception(JText::_('COM_HELLOWORLD_ERROR_MESSAGE_NOT_FOUND'), 404); } // Загружаем JSON строку параметров. $params = new JRegistry; $params->loadString($data->params); $data->params = $params; // Объединяем глобальные параметры с индивидуальными. $params = clone $this->getState('params'); $params->merge($data->params); $data->params = $params; $this->_item[$id] = $data; } return $this->_item[$id]; } /** * Метод для авто-заполнения состояния модели. * * Заметка. Вызов метода getState в этом методе приведет к рекурсии. * * @return void */ protected function populateState() { $app = JFactory::getApplication(); // Получаем Id сообщения из Запроса. $id = $app->input->getInt('id', 0); // Добавляем Id сообщения в состояние модели. $this->setState('message.id', $id); // Загружаем глобальные параметры. $params = $app->getParams(); // Добавляем параметры в состояние модели. $this->setState('params', $params); parent::populateState(); } }
Класс был значительно изменен. Мы убрали метод getTable()
, так как JTable
мы больше не используем. Дело в том, что нам необходимо получить категорию, а информация о ней хранится в таблице #__categories
. А как известно, класс JTable
используется для работы с одной таблицей, поэтому вместо него в метод getItem()
был добавлен запрос для выборки сообщения вместе с категорией. Мы также генерируем исключение, если запрос в базу данных вернул пустой результат. Мы отмечаем это исключение кодом
404
, который потом мы обработаем в представлении.
Тут же присутствует обработка параметров. И снова мы применяем удобный объект JRegistry для преобразования JSON строки в объект. Обратите внимание, что при объединении глобальных параметров с индивидуальными мы предварительно делаем копию объекта параметров c помощью clone. Глобальные параметры мы получаем в методе populateState()
.
Теперь необходимо изменить представление и шаблон.
site/views/helloworld/view.html.php
<?php // Запрет прямого доступа. defined('_JEXEC') or die; // Подключаем библиотеку представления Joomla. jimport('joomla.application.component.view'); /** * HTML представление сообщения компонента HelloWorld. */ class HelloWorldViewHelloWorld extends JViewLegacy { /** * Сообщение. * * @var object */ protected $item; /** * Переопределяем метод display класса JViewLegacy. * * @param string $tpl Имя файла шаблона. * * @throws Exception Если сообщение не найдено. * * @return void */ public function display($tpl = null) { try { // Получаем сообщение. $this->item = $this->get('Item'); // Подготавливаем документ. $this->_prepareDocument(); // Отображаем представление. parent::display($tpl); } catch (Exception $e) { if ($e->getCode() == 404) { // Сообщение не найдено. throw new Exception($e->getMessage(), 404); } JFactory::getApplication()->enqueueMessage(JText::_('COM_HELLOWORLD_ERROR_OCCURRED'), 'error'); JLog::add($e->getMessage(), JLog::ERROR, 'com_helloworld'); } } /** * Подготавливает документ. * * @return void */ protected function _prepareDocument() { $app = JFactory::getApplication(); $menus = $app->getMenu(); $title = null; // Так как приложение устанавливает заголовок страницы по умолчанию, // мы получаем его из пункта меню. $menu = $menus->getActive(); if ($menu) { $this->item->params->def('page_heading', $this->item->params->get('page_title', $menu->title)); } else { $this->item->params->def('page_heading', JText::_('COM_HELLOWORLD_DEFAULT_PAGE_TITLE')); } // Получаем заголовок страницы в браузере из параметров. $title = $this->item->params->get('page_title', ''); if (empty($title)) { $title = $app->getCfg('sitename'); } elseif ($app->getCfg('sitename_pagetitles', 0) == 1) { $title = JText::sprintf('JPAGETITLE', $app->getCfg('sitename'), $title); } elseif ($app->getCfg('sitename_pagetitles', 0) == 2) { $title = JText::sprintf('JPAGETITLE', $title, $app->getCfg('sitename')); } if (empty($title)) { $title = $this->item->greeting; } // Устанавливаем заголовок страницы в браузере. $this->document->setTitle($title); // Добавляем поддержку метаданных из пункта меню. if ($this->item->params->get('menu-meta_description')) { $this->document->setDescription($this->item->params->get('menu-meta_description')); } if ($this->item->params->get('menu-meta_keywords')) { $this->document->setMetadata('keywords', $this->item->params->get('menu-meta_keywords')); } if ($this->item->params->get('robots')) { $this->document->setMetadata('robots', $this->item->params->get('robots')); } } }
Помните, в модели мы генерировали исключение с кодом 404
? Теперь мы обрабатываем это исключение и генерируем новое исключение с кодом 404
. Далее Joomla перехватит это исключение, и в итоге для пустого результата мы получим стандартную страницу 404 с сообщением "Сообщение не найдено".
В методе _prepareDocument()
вместо $this->params
мы используем $this->item->params
, так как теперь параметры у нас хранятся в $this->item->params
.
site/views/helloworld/tmpl/default.php
<?php // Запрет прямого доступа. defined('_JEXEC') or die; ?> <?php if ($this->item->params->get('show_page_heading')) : ?> <h1> <?php echo $this->escape($this->item->params->get('page_heading')); ?> </h1> <?php endif; ?> <h2> <?php echo $this->item->greeting . (($this->item->category and $this->item->params->get('show_category')) ? (' (' . $this->item->category . ')') : ''); ?> </h2>
В шаблоне мы получаем параметр show_category
и в зависимости от его значения (1
или 0
) отображаем или не отображаем категорию в скобках.
Добавляем языковые константы
Откройте файл admin/language/en-GB/en-GB.com_helloworld.ini и добавьте:
COM_HELLOWORLD_CONFIGURATION="HelloWorld! Configuration"
COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_LABEL="Messages settings"
COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_DESC="Settings that will be applied to all messages by default."
COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_LABEL="Show category"
COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_DESC="If set to Show, the title of the message's category will show."
Откройте файл admin/language/ru-RU/ru-RU.com_helloworld.ini и добавьте:
COM_HELLOWORLD_CONFIGURATION="Конфигурация"
COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_LABEL="Параметры сообщения"
COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_DESC="Параметры вступят в силу для всех сообщений."
COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_LABEL="Выводить категорию"
COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_DESC="Если показать, то будет показываться и категория."
Откройте файл site/language/en-GB/en-GB.com_helloworld.ini и добавьте:
COM_HELLOWORLD_ERROR_MESSAGE_NOT_FOUND="Message not found"
Откройте файл site/language/ru-RU/ru-RU.com_helloworld.ini и добавьте:
COM_HELLOWORLD_ERROR_MESSAGE_NOT_FOUND="Сообщение не найдено"
Собираем пакет установки компонента
Не забудьте поменять номер версии в файле helloworld.xml:
<version>0.0.10</version>
Добавляем поддержку конфигурацию:
<filename>config.xml</filename>
helloworld.xml
<?xml version="1.0" encoding="utf-8"?> <extension type="component" version="2.5.0" method="upgrade"> <name>COM_HELLOWORLD</name> <!-- Следующие элементы необязательны --> <creationDate>Июль 2012</creationDate> <author>Вася Пупкин</author> <authorEmail>Ваш e-mail</authorEmail> <authorUrl>Ваш сайт</authorUrl> <copyright>Информация о копирайте</copyright> <license>Информация о лицензии</license> <!-- Версия записывается в таблицу компонентов --> <version>0.0.10</version> <!-- Описание необязательно --> <description>COM_HELLOWORLD_DESCRIPTION</description> <!-- Запускается при установке --> <install> <sql> <file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file> </sql> </install> <!-- Запускается при удалении --> <uninstall> <sql> <file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file> </sql> </uninstall> <!-- Запускается при обновлении --> <update> <schemas> <schemapath type="mysql">sql/updates/mysql</schemapath> </schemas> </update> <!-- Раздел основных файлов сайта --> <!-- Обратите внимание на значение аттрибута folder: Этот аттрибут описывает папку нашего пакета-установщика из которой должны копироваться файлы. Поэтому указанные в этом разделе файлы будут скопированы из папки /site/ нашего пакета-установщика в соответствующую папку установки. --> <files folder="site"> <filename>index.html</filename> <filename>controller.php</filename> <filename>helloworld.php</filename> <folder>language</folder> <folder>models</folder> <folder>views</folder> </files> <media destination="com_helloworld" folder="media"> <filename>index.html</filename> <folder>images</folder> </media> <!-- Администрирование --> <administration> <!-- Раздел Меню --> <menu img="../media/com_helloworld/images/hello-16x16.png">COM_HELLOWORLD_MENU</menu> <!-- Раздел основных файлов администрирования --> <!-- Обратите внимание на значение аттрибута folder: Этот аттрибут описывает папку нашего пакета-установщика из которой должны копироваться файлы. Поэтому указанные в этом разделе файлы будут скопированы из папки /admin/ нашего пакета-установщика в соответствующую папку установки. --> <files folder="admin"> <filename>index.html</filename> <filename>config.xml</filename> <filename>controller.php</filename> <filename>helloworld.php</filename> <folder>controllers</folder> <folder>helpers</folder> <folder>models</folder> <folder>sql</folder> <folder>tables</folder> <folder>views</folder> </files> <languages folder="admin"> <language tag="en-GB">language/en-GB/en-GB.com_helloworld.ini</language> <language tag="en-GB">language/en-GB/en-GB.com_helloworld.sys.ini</language> <language tag="ru-RU">language/ru-RU/ru-RU.com_helloworld.ini</language> <language tag="ru-RU">language/ru-RU/ru-RU.com_helloworld.sys.ini</language> </languages> </administration> </extension>
Содержимое директории с кодом:
helloworld.xml
site/index.html
site/helloworld.php
site/controller.php
site/language/index.html
site/language/en-GB/index.html
site/language/en-GB/en-GB.com_helloworld.ini
site/language/ru-RU/index.html
site/language/ru-RU/ru-RU.com_helloworld.ini
site/models/index.html
site/models/helloworld.php
site/views/index.html
site/views/helloworld/index.html
site/views/helloworld/view.html.php
site/views/helloworld/tmpl/index.html
site/views/helloworld/tmpl/default.xml
site/views/helloworld/tmpl/default.php
admin/index.html
admin/config.xml
admin/controller.php
admin/helloworld.php
admin/controllers/index.html
admin/controllers/helloworld.php
admin/controllers/helloworlds.php
admin/helpers/index.html
admin/helpers/helloworld.php
admin/language/index.html
admin/language/en-GB/index.html
admin/language/en-GB/en-GB.com_helloworld.ini
admin/language/en-GB/en-GB.com_helloworld.sys.ini
admin/language/ru-RU/index.html
admin/language/ru-RU/ru-RU.com_helloworld.ini
admin/language/ru-RU/ru-RU.com_helloworld.sys.ini
admin/models/index.html
admin/models/helloworld.php
admin/models/helloworlds.php
admin/models/fields/index.html
admin/models/fields/helloworld.php
admin/models/forms/index.html
admin/models/forms/helloworld.js
admin/models/forms/helloworld.xml
admin/models/rules/index.html
admin/models/rules/greeting.php
admin/sql/index.html
admin/sql/install.mysql.utf8.sql
admin/sql/uninstall.mysql.utf8.sql
admin/sql/updates/index.html
admin/sql/updates/mysql/index.html
admin/sql/updates/mysql/0.0.1.sql
admin/sql/updates/mysql/0.0.4.sql
admin/sql/updates/mysql/0.0.9.sql
admin/sql/updates/mysql/0.0.10.sql
admin/tables/index.html
admin/tables/helloworld.php
admin/views/index.html
admin/views/helloworld/index.html
admin/views/helloworld/view.html.php
admin/views/helloworld/submitbutton.js
admin/views/helloworld/tmpl/index.html
admin/views/helloworld/tmpl/edit.php
admin/views/helloworlds/index.html
admin/views/helloworlds/view.html.php
admin/views/helloworlds/tmpl/index.html
admin/views/helloworlds/tmpl/default.php
admin/views/helloworlds/tmpl/default_body.php
admin/views/helloworlds/tmpl/default_foot.php
admin/views/helloworlds/tmpl/default_head.php
language/index.html
language/en-GB/index.html
language/en-GB/en-GB.com_helloworld.sys.ini
language/ru-RU/index.html
language/ru-RU/ru-RU.com_helloworld.sys.ini
media/index.html
media/images/index.html
media/images/hello-16x16.png
media/images/hello-48x48.png
Запакуйте директорию в архивный файл (zip, tar, tar.gz, bz2) или скачайте его напрямую c GitHub. Далее установите его, используя менеджер расширений Joomla. Теперь мы можем конфигурировать общие параметры компонента и индивидуальные параметры сообщений.
В следующей части мы рассмотрим создание списков контроля доступов (ACL - Access Control List).
Код для этой части
Скачать com_helloworld часть 10
Актуальный код части 10 на GitHub