Создание компонента для Joomla

Часть 16 - добавляем фильтры и учимся создавать свои

Joomla

Часть 16 - добавляем фильтры и учимся создавать свои

Фильтры значительно улучшают удобство управления списком записей в панели администратора.

В общей сложности мы добавим три фильтра:

  1. Поиск – позволяет фильтровать по тексту сообщения.
  2. Фильтр состояния записи.
  3. Фильтр категорий.

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

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

Изменяем модель списка сообщений

Итак, открываем файл admin/models/helloworlds.php и начинаем вносить изменения.

Первое, что необходимо изменить в модели, это добавить список валидных полей (по которым будет выполняться фильтрация и сортировка) в конструктор. В части 14 мы уже добавили нужные нам поля для возможности сортировки и их же мы будем использовать для фильтров. Поэтому нам осталось добавить только поле category_title, которое будет алиасом поля title таблицы категорий. Таким образом мы сможем выполнять сортировку по названию категории:


/**
 * Конструктор.
 *
 * @param   array  $config  Массив с конфигурационными параметрами.
 */
public function __construct($config = array())
{
    // Добавляем валидные поля для фильтров и сортировки.
    if (empty($config['filter_fields']))
    {
        $config['filter_fields'] = array(
            'id', 'h.id',
            'greeting', 'h.greeting',
            'category_title',
            'state', 'h.state',
            'ordering', 'h.ordering',
        );
    }
 
    parent::__construct($config);
}

Обратили внимание, что у всех полей в конструкторе появился префикс h. ? Все дело в том, что мы будем делать выборку не только из одной таблицы #__helloworld (префикс h.), но и из таблицы #__categories (префикс с.), чтобы отобразить название категории в списке сообщений. Эти префиксы были добавлены ко всем полям в коде модели.

Выборка данных для формирования списка у нас происходит в методе getListQuery(). Давайте посмотрим, как он изменился:


/**
 * Метод для построения SQL запроса для загрузки списка данных.
 *
 * @return  string  SQL запрос.
 */
protected function getListQuery()
{
    // Создаем новый query объект.
    $db = JFactory::getDbo();
    $query = $db->getQuery(true);
 
    // Выбераем поля.
    $query->select('h.id, h.greeting, h.state, h.ordering');
 
    // Из таблицы helloworld.
    $query->from('#__helloworld AS h');
 
    // Присоединяем таблицу категорий.
    $query->select('c.title AS category_title');
    $query->leftJoin('#__categories AS c ON c.id = h.catid');
 
    // Фильтруем по состоянию.
    $published = $this->getState('filter.state');
 
    if (is_numeric($published))
    {
        $query->where('h.state = ' . (int) $published);
    }
    elseif ($published === '')
    {
        $query->where('(h.state = 0 OR h.state = 1)');
    }
 
    // Фильтруем по категории.
    $categoryId = $this->getState('filter.category_id');
 
    if (is_numeric($categoryId))
    {
        $categoryTable = JTable::getInstance('Category', 'JTable');
        $categoryTable->load($categoryId);
        $rgt = $categoryTable->rgt;
        $lft = $categoryTable->lft;
        $query->where('c.lft >= ' . (int) $lft);
        $query->where('c.rgt <= ' . (int) $rgt);
    }
 
    // Фильтруем по поиску в тексте сообщения.
    $search = $this->getState('filter.search');
 
    if (!empty($search))
    {
        $search = $db->quote('%' . $db->escape($search, true) . '%', false);
        $query->where('h.greeting LIKE ' . $search);
    }
 
    // Добавляем сортировку.
    $orderCol  = $this->state->get('list.ordering', 'h.id');
    $orderDirn = $this->state->get('list.direction', 'desc');
    $query->order($db->escape($orderCol . ' ' . $orderDirn));
 
    return $query;
}

Изменений много. Мы видим, что появилась выборка категорий:


// Присоединяем таблицу категорий.
$query->select('c.title AS category_title');
$query->leftJoin('#__categories AS c ON c.id = h.catid');

А далее следует целый ряд условий для фильтров: по состоянию, по категории и по поиску в тексте сообщения. Обратите внимание на то, как экранируется строка перед выполнением полнотекстового поиска:

$search = $db->quote('%' . $db->escape($search, true) . '%', false);

Сначала с помощью метода escape() мы экранируем специальные символы типа "%", которые могут содержаться в поисковом запросе. Затем мы обрамляем запрос в кавычки, но не экранируем его повторно, передавая вторым аргументом false в метод quote().

Значения фильтров мы получаем из состояния модели. Поэтому необходимо добавить получение этих значений в метод populateState():


/**
 * Метод для авто-заполнения состояния модели.
 *
 * @param   string  $ordering   Поле сортировки.
 * @param   string  $direction  Направление сортировки (asc|desc).
 *
 * @return  void
 */
protected function populateState($ordering = null, $direction = null)
{
    // Получаем и устанавливаем значение фильтра состояния.
    $published = $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'string');
    $this->setState('filter.state', $published);
 
    // Получаем и устанавливаем значение фильтра категории.
    $categoryId = $this->getUserStateFromRequest($this->context . '.filter.category_id', 'filter_category_id');
    $this->setState('filter.category_id', $categoryId);
 
    // Получаем и устанавливаем значение фильтра поиска по тексту сообщения.
    $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search');
    $this->setState('filter.search', $search);
 
    parent::populateState('h.id', 'desc');
}

Здесь мы получаем и устанавливаем значения наших фильтров. При этом мы используем метод getUserStateFromRequest(), который доступен нам из родительского класса JModelList. Этот метод получает значение переменной состояния пользователя (сессии) и заново устанавливает это значение в случае его изменения. Для того, чтобы значения в состоянии пользователя были уникальны между различным компонентами, мы используем свойство $this->context из родительского класса JModel, которое устанавливается в его конструкторе.

В итоге мы получаем эффект запоминания значения фильтров. Вероятнее всего вы обращали на это внимание при работе с Joomla – фильтры сохраняются при переходе между компонентами до тех пор, пока вы не выйдете из панели администратора. Только тогда происходит обнуление состояния пользователя и соответственно фильтров.

Нам также необходимо добавить метод getStoreId():


/**
 * Метод для получения store id, которое основывается на состоянии модели.
 *
 * @param   string  $id  Идентификационная строка для генерации store id.
 *
 * @return  string  Store id.
 */
protected function getStoreId($id = '')
{
    // Компилируем store id.
    $id .= ':' . $this->getState('filter.search');
    $id .= ':' . $this->getState('filter.state');
    $id .= ':' . $this->getState('filter.category_id');
 
    return parent::getStoreId($id);
}

Этот метод используется для кэширования данных. В нем мы учитываем текущее состояние фильтров, которое необходимо для генерации уникального store id. Оно повсеместно используется в родительском классе JModelList, где является ключом в свойстве-массиве $cache.

Предположим, вы установили фильтр состояния в «Опубликовано». Модель сделает выборку и запомнит её в своем внутреннем кэше - свойстве $cache. Если вы измените фильтр на другое значение и потом снова вернетесь к «Опубликовано», модель не будет выполнять запрос к базе данных, а возьмет данные из внутреннего кэша.

Изменяем хелпер

Чтобы кнопка настроек компонента не исчезала каждый раз при выборе категории в фильтре, в файле хелпера admin/helpers/helloworld.php необходимо изменить строку

if ($section == 'message')

на

if ($section == 'category' || $section == 'message')

Изменяем представление списка сообщений

В представлении списка сообщений admin/views/helloworlds/view.html.php нам необходимо учитывать фильтр категорий при получении доступов пользователя. Поэтому в методе display() меняем строку

$this->canDo = HelloWorldHelper::getActions();

на

$this->canDo = HelloWorldHelper::getActions($this->state->get('filter.category_id'));

Так как у нас теперь есть фильтр состояния сообщения, мы можем изменить логику удаления сообщений. Первично мы будем помещать их в корзину, а удалять можно будет только те сообщения, которые уже были помещены в корзину. Для этого немного изменим метод addToolBar():


/**
 * Устанавливает панель инструментов.
 *
 * @return void
 */
protected function addToolBar()
{
    JToolBarHelper::title(JText::_('COM_HELLOWORLD_MANAGER_HELLOWORLDS'), 'helloworld');
 
    if ($this->canDo->get('core.create'))
    {
        JToolBarHelper::addNew('helloworld.add');
    }
 
    if ($this->canDo->get('core.edit'))
    {
        JToolBarHelper::editList('helloworld.edit');
    }
 
    if ($this->canDo->get('core.edit.state'))
    {
        JToolBarHelper::divider();
        JToolbarHelper::publish('helloworlds.publish', 'JTOOLBAR_PUBLISH', true);
        JToolbarHelper::unpublish('helloworlds.unpublish', 'JTOOLBAR_UNPUBLISH', true);
        JToolBarHelper::divider();
        JToolBarHelper::archiveList('helloworlds.archive');
    }
 
    if ($this->state->get('filter.state') == -2 && $this->canDo->get('core.delete'))
    {
        JToolBarHelper::deleteList('', 'helloworlds.delete', 'JTOOLBAR_EMPTY_TRASH');
    }
    elseif ($this->canDo->get('core.edit.state'))
    {
        JToolBarHelper::trash('helloworlds.trash');
    }
 
    if ($this->canDo->get('core.admin'))
    {
        JToolBarHelper::divider();
        JToolBarHelper::preferences('com_helloworld');
    }
}

Теперь, когда значение фильтра состояния будет равно -2 (в корзине) у нас будет появляться кнопка «Очистить корзину». В противном случае вместо неё будет отображаться кнопка «В корзину».

Панель инструментов

Изменяем шаблоны списка сообщений

Сначала изменим основной шаблон admin/views/helloworlds/tmpl/default.php и добавим в него фильтры:

<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
 
// Загружаем тултипы.
JHtml::_('behavior.tooltip');
?>
<form action="<?php echo JRoute::_('index.php?option=com_helloworld'); ?>" method="post" name="adminForm" id="adminForm">
    <fieldset id="filter-bar">
        <div>
            <label for="filter_search"><?php echo JText::_('JSEARCH_FILTER_LABEL'); ?></label>
            <input type="text" name="filter_search" id="filter_search" value="<?php echo $this->escape($this->state->get('filter.search')); ?>" title="<?php echo JText::_('COM_HELLOWORLD_FILTER_SEARCH_DESC'); ?>" />
            <button type="submit"><?php echo JText::_('JSEARCH_FILTER_SUBMIT'); ?></button>
            <button type="button" onclick="document.id('filter_search').value='';this.form.submit();"><?php echo JText::_('JSEARCH_FILTER_CLEAR'); ?></button>
        </div>
        <div>
            <select name="filter_state" onchange="this.form.submit()">
                <option value=""><?php echo JText::_('JOPTION_SELECT_PUBLISHED');?></option>
                <?php echo JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), 'value', 'text', $this->state->get('filter.state'), true);?>
            </select>
            <select name="filter_category_id" onchange="this.form.submit()">
                <option value=""><?php echo JText::_('JOPTION_SELECT_CATEGORY');?></option>
                <?php echo JHtml::_('select.options', JHtml::_('category.options', 'com_helloworld'), 'value', 'text', $this->state->get('filter.category_id'));?>
            </select>
        </div>
    </fieldset>
    <div> </div>
    <table>
        <thead><?php echo $this->loadTemplate('head');?></thead>
        <tbody><?php echo $this->loadTemplate('body');?></tbody>
        <tfoot><?php echo $this->loadTemplate('foot');?></tfoot>
    </table>
    <div>
        <input type="hidden" name="task" value="" />
        <input type="hidden" name="boxchecked" value="0" />
        <input type="hidden" name="filter_order" value="<?php echo $this->escape($this->state->get('list.ordering')); ?>" />
        <input type="hidden" name="filter_order_Dir" value="<?php echo $this->escape($this->state->get('list.direction')); ?>" />
        <?php echo JHtml::_('form.token'); ?>
    </div>
</form>

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

Текущие значения фильтров мы берем из состояния модели. Также хотелось бы отметить, что любое изменение фильтров приводит к отправке формы с помощью this.form.submit().

Далее изменим суб-шаблон заголовков списков admin/views/helloworlds/tmpl/default_head.php и добавим заголовок категории:


<th width="10%">
    <?php echo JHtml::_('grid.sort', 'JCATEGORY', 'category_title', $listDirn, $listOrder); ?>
</th>

В суб-шаблоне admin/views/helloworlds/tmpl/default_body.php мы выводим название категории:


<td>
    <?php echo $this->escape($item->category_title); ?>
</td>

А в суб-шаблоне admin/views/helloworlds/tmpl/default_foot.php мыувеличиваем значение colspan:


<tr>
    <td colspan="6"><?php echo $this->pagination->getListFooter(); ?></td>
</tr>

В итоге получается вот такая картинка:

Панель фильтров

Изменяем контроллер сообщения

Открываем файл admin/controller/helloworld.php и вносим одно небольшое изменение в метод allowAdd() – меняем строку

$categoryId = JArrayHelper::getValue($data, 'catid', 0, 'int');

на

$categoryId = JArrayHelper::getValue($data, 'catid', JFactory::getApplication()->input->getInt('filter_category_id', 0), 'int');

Здесь мы просто добавили значение по умолчанию, которое берется из фильтра.

Изменяем файл формы

В файле формы необходимо добавить два значения состояния:

  • в корзине
  • в архиве

Откройте файл admin/models/forms/helloworld.xml и добавьте для поля state эти два значения:

<field
    name="state"
    type="list"
    label="JSTATUS"
    description="JFIELD_PUBLISHED_DESC"
    class="inputbox"
    size="1"
    default="1"
>
    <option value="1">JPUBLISHED</option>
    <option value="0">JUNPUBLISHED</option>
    <option value="2">JARCHIVED</option>
    <option value="-2">JTRASHED</option>
</field>

Добавляем языковые константы

Откройте файл admin/language/en-GB/en-GB.com_helloworld.ini и добавьте:

COM_HELLOWORLD_FILTER_SEARCH_DESC="You can search by any text in greeting."
COM_HELLOWORLD_N_ITEMS_ARCHIVED_1="One message archived"
COM_HELLOWORLD_N_ITEMS_ARCHIVED="%d messages archived"
COM_HELLOWORLD_N_ITEMS_TRASHED_1="One message trashed"
COM_HELLOWORLD_N_ITEMS_TRASHED="%d messages trashed"

Откройте файл admin/language/ru-RU/ru-RU.com_helloworld.ini и добавьте:

COM_HELLOWORLD_FILTER_SEARCH_DESC="Вы можете искать по любому тексту в приветствии."
COM_HELLOWORLD_N_ITEMS_ARCHIVED_1="1 сообщение помещено в Архив"
COM_HELLOWORLD_N_ITEMS_ARCHIVED_2="%d сообщения помещено в Архив"
COM_HELLOWORLD_N_ITEMS_ARCHIVED_MORE="%d сообщений помещено в Архив"
COM_HELLOWORLD_N_ITEMS_TRASHED_1="1 сообщение помещено в Корзину"
COM_HELLOWORLD_N_ITEMS_TRASHED_2="%d сообщения помещено в Корзину"
COM_HELLOWORLD_N_ITEMS_TRASHED_MORE="%d сообщений помещено в Корзину"

 

Собираем пакет установки компонента

Не забудьте поменять номер версии в файле helloworld.xml:

<version>0.0.16</version>

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.16</version>
    <!-- Описание необязательно -->
    <description>COM_HELLOWORLD_DESCRIPTION</description>
    <!-- Запускается при установке/удалении/обновлении -->
    <scriptfile>script.php</scriptfile>
    <!-- Запускается при установке -->
    <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>access.xml</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>

    
    <!-- Сервер обновлений -->
    <updateservers>
        <!-- Заметка: Не допускаются пробелы или переносы строк между тегам server -->
        <server type="extension" priority="1" name="Сайт обновлений компонента Hello World!">http://вашдомен.ru/update/helloworld-update.xml</server>
    </updateservers>
</extension>

Содержимое директории с кодом:

helloworld.xml
script.php
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/access.xml
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/sql/updates/mysql/0.0.12.sql
admin/sql/updates/mysql/0.0.14.sql
admin/sql/updates/mysql/0.0.15.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. Теперь в списке записей появились фильтры.

Код для этой части

Скачать com_helloworld часть 16

Актуальный код части 16 на GitHub

Создаем свои собственные фильтры с помощью класса JHtml

Создавать свои собственные фильтры с JHtml довольно просто. Давайте представим, что в Joomla не доступен встроенный фильтр состояния, поэтому нам необходимо создать свой.

Первое, что нужно сделать, это указать классу JHtml, где искать файлы, в которых определены наши функции для работы с фильтрами. Делается это с помощью метода addIncludePath(). Предположим, что мы будем хранить эти файлы в папке /admin/helpers/html, тогда в точке входа /admin/helloworld.php мы добавляем:

// Подключаем HTML хелперы.
JHtml::addIncludePath(dirname(__FILE__) . '/helpers/html');

Далее создаем в этой папке файл filters.php со следующим содержимым:

<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
 
/**
 * HTML фильтры для HelloWorld компонента.
 */
abstract class HelloWorldHtmlFilters
{
    /**
     * Метод для получения списка опций состояния.
     *
     * @return  array  $options  Массив опций.
     */
    public static function stateOptions()
    {
        $options = array();
 
        $options[] = JHtml::_('select.option', '1', 'JPUBLISHED');
        $options[] = JHtml::_('select.option', '0', 'JUNPUBLISHED');
        $options[] = JHtml::_('select.option', '2', 'JARCHIVED');
        $options[] = JHtml::_('select.option', '-2', 'JTRASHED');
        $options[] = JHtml::_('select.option', '*', 'JALL');
 
        return $options;
    }
}

Теперь мы можем заменить строку

<?php echo JHtml::_('select.options', JHtml::_('filters.state'), 'value', 'text', $this->state->get('filter.state'), true); ?>

на

<?php echo JHtml::_('select.options', JHtml::_('helloworldhtml.filters.stateOptions'), 'value', 'text', $this->state->get('filter.state'), true); ?>

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

Но как JHtml определяет, что нужно вызвать именно метод stateOptions() класса HelloWorldHtmlFilters из файла filters.php? Я думаю, что вы уже догадались, что ответ кроется в ключе 'helloworldhtml.filters.stateOptions', который JHtml разбирает на следующие составляющие:

  • первый сегмент – префикс класса, а если не указан, то JHtml;
  • второй сегмент – имя файла
  • третий сегмент – метод класса

При этом для получения имени класса JHtml объединяет первый и второй сегмент. Таким образом, зная этот ключ, Вы можете легко найти имеющиеся в Joomla классы, которые работают не только с фильтрами, но с различными элементами типа 'date', 'sliders' и т.п. Например, используемый нами в фильтрах ключ 'select.options' приведет к файлу libraries/joomla/html/html/select.php в котором Вы найдете класс JHtmlSelect и метод options().

Но, мы можем пойти еще дальше и создать целый select-фильтр, а не просто массив опций:

/**
 * Метод для получения фильтра состояния.
 *
 * @param   mixed  $selected  Значение выбранной опции.
 *
 * @return  string  Фильтр состояния.
 */
public static function state($selected)
{
    $options = array();
 
    $options[] = JHtml::_('select.option', '', 'JOPTION_SELECT_PUBLISHED');
    $options = array_merge($options, self::stateOptions());
 
    $attribs = 'class="inputbox" onchange="this.form.submit()"';
 
    return JHtml::_('select.genericlist', $options, 'filter_state', $attribs, 'value', 'text', $selected, null, true);
}

Теперь мы можем заменить строку

<?php echo JHtml::_('select.options', JHtml::_('helloworldhtml.filters.stateOptions'), 'value', 'text', $this->state->get('filter.state'), true); ?>

на еще более простой вариант

<?php echo JHtml::_('helloworldhtml.filters.state', $this->state->get('filter.state')) ; ?>

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

JLoader::register('HelloWorldHtmlFilters', dirname(__FILE__) . '/helpers/html/filters.php');

И дальше выводить фильтр вот так:

<?php echo HelloWorldHtmlFilters::state($this->state->get('filter.state')); ?>

Не знаю, какой вариант предпочтете вы, но лично мне больше по душе использование JHtml.

 

Dmitry Rekun
Работаю в банковской сфере, а с веб-разработкой (непосредственно с Joomla) столкнулся в 2007 году. Теперь это моё хобби и время от времени вторая работа. Какое-то время вёл свой блог, но решил попробовать работать в команде. И вот c 2012 года я здесь :)