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

Часть 7 - панель управления

Joomla

Часть 7 - панель управления

Создание панели инструментов

В Joomla администратор сайта обычно управляет компонентами с помощью панели инструментов и различных действий, которые связаны с этой панелью. Давайте создадим заголовок с иконкой и панель инструментов для нашего компонента. Для этого необходимо отредактировать файл admin/views/helloworlds/view.html.php:

<?php
 // Запрет прямого доступа.
 defined('_JEXEC') or die; // Подключаем библиотеку представления Joomla.
 jimport('joomla.application.component.view');
 
 /**
  * HTML представление списка сообщений компонента HelloWorld.
  */
 class HelloWorldViewHelloWorlds extends JViewLegacy
 {
     /**
      * Сообщения.
      *
      * @var  array
      */
     protected $items;
 
     /**
      * Постраничная навигация.
      *
      * @var  object
      */
     protected $pagination;
 
     /**
      * Отображаем список сообщений.
      *
      * @param   string  $tpl  Имя файла шаблона.
      *
      * @return  void
      *
      * @throws  Exception
      */
     public function display($tpl = null)
     {
         try
         {
             // Получаем данные из модели.
             $this->items = $this->get('Items');
 
             // Получаем объект постраничной навигации.
             $this->pagination = $this->get('Pagination');
 
             // Устанавливаем панель инструментов.
             $this->addToolBar();
 
             // Отображаем представление.
             parent::display($tpl);
 
         }
         catch (Exception $e)
         {
             throw new Exception($e->getMessage());
         }
     }
 
     /**
      * Устанавливает панель инструментов.
      *
      * @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');
     }
 }
 

В методе addToolBar() мы используем класс JToolBarHelper для добавления элементов в панель инструментов. Этот класс доступен из любой точки администраторской части, так как он подключается непосредственно в файле administrator/index.php:

require_once JPATH_BASE.'/includes/toolbar.php';

Функции JToolBarHelper::title мы передаем второй параметр helloworld. Это добавит к заголовку компонента css-класс helloworld, что позволит нам далее настроить иконку заголовка. Также мы добавили кнопки добавления, редактирования записи и удаления списка записей. Вы можете найти другие классические функции по управлению в файле administrator/includes/toolbar.php.

JToolBarHelper::divider(); просто выводит символ разделителя и помогает визуально отделить различные группы кнопок.

Панель управления - кнопки

Так как представление теперь может выполнять некоторые действия, мы должны добавить входные данные в файл 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">
    <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" />
        <?php echo JHtml::_('form.token'); ?>
    </div>
</form>

Теперь через скрытое поле task мы передаем задачу, которая подставляется исходя из того, какую кнопку в панели инструментов мы нажали. Скрытое поле boxchecked позволяет Joomla определить, выбрана ли хоть одна запись или нет.

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

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

  • helloworlds.delete
  • helloworld.edit
  • helloworld.add

Это так называемые составные задачи (controller.task). Поэтому необходимо добавить ещё два контроллера: HelloWorldControllerHelloWorlds и HelloWorldControllerHelloWorld. Подробнее о субконтроллерах можно почитать здесь:

http://docs.joomla.org/JController_and_its_subclass_usage_overview

Создайте файл admin/controllers/helloworlds.php со следующим кодом:

<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
 
// Подключаем библиотеку controlleradmin Joomla.
jimport('joomla.application.component.controlleradmin');
 
/**
 * HelloWorlds контроллер.
 */
class HelloWorldControllerHelloWorlds extends JControllerAdmin
{
    /**
     * Прокси метод для getModel.
     *
     * @param   string  $name    Имя класса модели.
     * @param   string  $prefix  Префикс класса модели.
     *
     * @return  object  Объект модели.
     */
    public function getModel($name = 'HelloWorld', $prefix = 'HelloWorldModel')
    {
        return parent::getModel($name, $prefix, array('ignore_request' => true));
    }
}

Мы переопределили метод getModel для того, чтобы родительский класс JControllerAdmin мог получить доступ к классу нашей модели HelloWorldModelHelloWorld и корректно выполнять удаление записей с помощью метода delete.

Создайте файл admin/controllers/helloworld.php со следующим кодом:

<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
 
// Подключаем библиотеку controllerform Joomla.
jimport('joomla.application.component.controllerform');
 
/**
 * HelloWorld контроллер.
 */
class HelloWorldControllerHelloWorld extends JControllerForm
{
}

Этот класс пустой, потому что необходимые нам методы add и edit расположены в родительском классе JControllerForm.

Добавляем представление для редактирования

Создайте файл admin/views/helloworld/view.html.php со следующим кодом:

<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
 
// Подключаем библиотеку представления Joomla.
jimport('joomla.application.component.view');
 
/**
 * HTML представление редактирования сообщения.
 */
class HelloWorldViewHelloWorld extends JViewLegacy
{
    /**
     * Сообщение.
     *
     * @var  object
     */
    protected $item;
 
    /**
     * Объект формы.
     *
     * @var  array
     */
    protected $form;
 
    /**
     * Отображает представление.
     *
     * @param   string  $tpl  Имя файла шаблона.
     *
     * @return  void
     *
     * @throws  Exception
     */
    public function display($tpl = null)
    {
        try
        {
            // Получаем данные из модели.
            $this->form = $this->get('Form');
            $this->item = $this->get('Item');
 
            // Устанавливаем панель инструментов.
            $this->addToolBar();
 
            // Отображаем представление.
            parent::display($tpl);
        }
        catch (Exception $e)
        {
            throw new Exception($e->getMessage());
        }
    }
 
    /**
     * Устанавливает панель инструментов.
     *
     * @return  void
     */
    protected function addToolBar()
    {
        JFactory::getApplication()->input->set('hidemainmenu', true);
        $isNew = ($this->item->id == 0);
 
        JToolBarHelper::title($isNew ? JText::_('COM_HELLOWORLD_MANAGER_HELLOWORLD_NEW') : JText::_('COM_HELLOWORLD_MANAGER_HELLOWORLD_EDIT'), 'helloworld');
        JToolBarHelper::apply('helloworld.apply', 'JTOOLBAR_APPLY');
        JToolBarHelper::save('helloworld.save');
        JToolBarHelper::cancel('helloworld.cancel', $isNew ? 'JTOOLBAR_CANCEL' : 'JTOOLBAR_CLOSE');
    }
}

В режиме добавления/редактирования записи мы убираем возможность пользоваться основным администраторским меню с помощью hidemainmenu. Также в зависимости от режима (добавление или редактирование) мы изменяем текст заголовка и текст под кнопками в панели.

Это представление будет отображать данные с помощью шаблона admin/views/helloworld/tmpl/edit.php:

<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
 
// Загружаем тултипы.
JHtml::_('behavior.tooltip');
?>
<form action="<?php echo JRoute::_('index.php?option=com_helloworld&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="helloworld-form">
    <fieldset>
        <legend><?php echo JText::_('COM_HELLOWORLD_HELLOWORLD_DETAILS'); ?></legend>
        <ul>
            <?php foreach ($this->form->getFieldset() as $field) : ?>
                <li><?php echo $field->label; echo $field->input; ?></li>
            <?php endforeach; ?>
        </ul>
    </fieldset>
    <div>
        <input type="hidden" name="task" value="" />
        <?php echo JHtml::_('form.token'); ?>
    </div>
</form>

В шаблоне мы используем метод getFieldset() для получения доступа к полям формы (в виде массива объектов класса JFormField), которую мы получаем с помощью модели.

Добавляем модель

Представление HelloWorldViewHelloWorld запрашиавает форму и данные из модели. Эта модель должна содержать методы getTable(), getForm() и loadData(). Создайте файл admin/models/helloworld.php со следующим кодом:

<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
 
// Подключаем библиотеку modeladmin Joomla.
jimport('joomla.application.component.modeladmin');
 
/**
 * Модель HelloWorld.
 */
class HelloWorldModelHelloWorld extends JModelAdmin
{
    /**
     * Возвращает ссылку на объект таблицы, всегда его создавая.
     *
     * @param   string  $type    Тип таблицы для подключения.
     * @param   string  $prefix  Префикс класса таблицы. Необязателен.
     * @param   array   $config  Конфигурационный массив. Необязателен.
     *
     * @return  JTable  Объект JTable.
     */
    public function getTable($type = 'HelloWorld', $prefix = 'HelloWorldTable', $config = array())
    {
        return JTable::getInstance($type, $prefix, $config);
    }
 
    /**
     * Метод для получения формы.
     *
     * @param   array    $data      Данные для формы.
     * @param   boolean  $loadData  True, если форма загружает свои данные (по умолчанию), false если нет.
     *
     * @return  mixed  Объект JForm в случае успеха, в противном случае false.
     */
    public function getForm($data = array(), $loadData = true)
    {
        // Получаем форму.
        $form = $this->loadForm(
            $this->option . '.helloworld', 'helloworld', array('control' => 'jform', 'load_data' => $loadData)
        );
 
        if (empty($form))
        {
            return false;
        }
 
        return $form;
    }
 
    /**
     * Метод для получения данных, которые должны быть загружены в форму.
     *
     * @return  mixed  Данные для формы.
     */
    protected function loadFormData()
    {
        // Проверка сессии на наличие ранее введеных в форму данных.
        $data = JFactory::getApplication()->getUserState($this->option . '.edit.helloworld.data', array());
 
        if (empty($data))
        {
            $data = $this->getItem();
        }
 
        return $data;
    }
}

Эта модель наследуется от класса JModelAdmin и использует метод loadForm() для получения формы. Обратите внимание, что мы используем свойство $this->option, значение которого равно com_helloworld. Оно определяется автоматически в конструкторе родительского класса JModel. Таким образом мы не привязываемся к названию нашего компонента, и если вдруг нам захочется его изменить, то мы сможем это сделать не меняя наш код.

Итак, метод loadForm() ищет формы в папке форм, которые по умолчанию находятся в models/forms. Создайте файл формы admin/models/forms/helloworld.xml:

<?xml version="1.0" encoding="utf-8"?>
 <form>
     <fieldset>
         <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"
             default=""
         />
     </fieldset>
 </form>

Названия полей формы совпадают с названиями полей в таблице базы данных. Таким образом наш класс таблицы HelloWorldTableHelloWorld сможет сохранить значения полей формы в соответствующих полях таблицы базы данных. Обратите внимание на скрытое поле id:

<field
    name="id"
    type="hidden"
/>

Для новой записи значение не указывается, а для существующей - это id записи из базы. На основании этого класс таблицы оперделяет, добавлять или обновлять данные в базе.

Изменяем точку входа

Для использования иконки 48x48px в заголовке, внесем изменения в файл точки входа admin/helloworld.php - с помощью метода addStyleDeclaration класса JDocument добавим для неё css-стиль:

<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
 
// Устанавливаем обработку ошибок в режим использования Exception.
JError::$legacy = false;
 
// Устанавливаем некоторые глобальные свойства.
$document = JFactory::getDocument();
$document->addStyleDeclaration('.icon-48-helloworld {background-image: url(../media/com_helloworld/images/hello-48x48.png);}');
 
// Подключаем библиотеку контроллера Joomla.
jimport('joomla.application.component.controller');
 
// Получаем экземпляр контроллера с префиксом HelloWorld.
$controller = JControllerLegacy::getInstance('HelloWorld');
 
// Исполняем задачу task из Запроса.
$input = JFactory::getApplication()->input;
$controller->execute($input->getCmd('task', 'display'));
 
// Перенаправляем, если перенаправление установлено в контроллере.
$controller->redirect();

В итоге получится вот такой симпатичный заголовок:

Панель управления - заголовок компонента

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

Откройте файл admin/language/en-GB/en-GB.com_helloworld.ini и замените код на следующий:

COM_HELLOWORLD_ADMINISTRATION="HelloWorld - Administration"
COM_HELLOWORLD_HELLOWORLD_CREATING="HelloWorld - Creating"
COM_HELLOWORLD_HELLOWORLD_DETAILS="Details"
COM_HELLOWORLD_HELLOWORLD_EDITING="HelloWorld - Editing"
COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_DESC="This message will be displayed"
COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_LABEL="Message"
COM_HELLOWORLD_HELLOWORLD_HEADING_GREETING="Greeting"
COM_HELLOWORLD_HELLOWORLD_HEADING_ID="ID"
COM_HELLOWORLD_MANAGER_HELLOWORLD_EDIT="HelloWorld manager: Edit Message"
COM_HELLOWORLD_MANAGER_HELLOWORLD_NEW="HelloWorld manager: New Message"
COM_HELLOWORLD_MANAGER_HELLOWORLDS="HelloWorld manager"
COM_HELLOWORLD_N_ITEMS_DELETED_1="One message deleted"
COM_HELLOWORLD_N_ITEMS_DELETED_MORE="%d messages deleted"

Откройте файл admin/language/ru-RU/ru-RU.com_helloworld.ini и замените код на следующий:

COM_HELLOWORLD_ADMINISTRATION="Hello World! - Администрирование"
COM_HELLOWORLD_HELLOWORLD_CREATING="Hello World! - Создание"
COM_HELLOWORLD_HELLOWORLD_DETAILS="Детали"
COM_HELLOWORLD_HELLOWORLD_EDITING="Hello World! - Редактирование"
COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_DESC="Сообщение для отображения"
COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_LABEL="Сообщение"
COM_HELLOWORLD_HELLOWORLD_HEADING_GREETING="Приветствие"
COM_HELLOWORLD_HELLOWORLD_HEADING_ID="ID"
COM_HELLOWORLD_MANAGER_HELLOWORLD_EDIT="Hello World!: Изменить сообщение"
COM_HELLOWORLD_MANAGER_HELLOWORLD_NEW="Hello World!: Добавить сообщение"
COM_HELLOWORLD_MANAGER_HELLOWORLDS="Управление Hello World!"
COM_HELLOWORLD_N_ITEMS_DELETED_1="Одно сообщение удалено"
COM_HELLOWORLD_N_ITEMS_DELETED_2="%d сообщения удалено"
COM_HELLOWORLD_N_ITEMS_DELETED_MORE="%d сообщений удалено"

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

Создайте две png-иконки для нашего компонента размером 16х16px и 48х48px пикселей, назовите их hello-16x16.png и hello-48x48.png и сохраните в папке media/images/.

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

<version>0.0.7</version>

Добавляем поддержку контроллеров:

<folder>controllers</folder>

Добавляем поддержку медиа:

<media destination="com_helloworld" folder="media">
    <filename>index.html</filename>
    <folder>images</folder>
</media>

Добавляем поддержку икноки в пункте меню:

<menu img="../media/com_helloworld/images/hello-16x16.png">COM_HELLOWORLD_MENU</menu>

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.7</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>controller.php</filename>
             <filename>helloworld.php</filename>
             <folder>controllers</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/controller.php
admin/helloworld.php
admin/controllers/index.html
admin/controllers/helloworld.php
admin/controllers/helloworlds.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.xml
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/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/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 часть 7

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

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