Печать

Создание MVC компонента Joomla 1.5 - Основы фреймворка для Back-end

Добавление функциональности

Итак, пока наш администраторский раздел не очень полезен. Пока он не делает ничего, кроме отображений содержимого базы данных.

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

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

Возможно, вы обратили внимание на панель инструментов, отображаемую вверху панелей администратора компонент Joomla. Нашему компоненту она также необходима. Joomla облегчает ее создание. Добавим кнопки Удалить записи, Изменить записи, и Создать новые записи. Также добавим заголовок, который будет отображаться на нашей панели инструментов.

Это можно сделать, добавив немного кода в представление. Чтобы добавить кнопки, используем статические методы из класса JToolBarHelper. Код выглядит так:

JToolBarHelper::title(   JText::_( 'Hello Manager' ), 'generic.png' );
JToolBarHelper::deleteList();
JToolBarHelper::editListX();
JToolBarHelper::addNewX();

Эти три метода создают соответствующие кнопки. Метод deleteList() может принимать три параметра: первый параметр является строкой, спрашивающей пользователя о подтверждении удаления. Второй параметр является задачей, которая отправляется вместе с запросом (по умолчанию "remove"), а третий - текст, отображаемый под кнопкой.

Методы editListX() и addNewX() могут получать два дополнительных параметра. Первый - задача (по умолчанию - соответственно, edit и add), второй - текст, отображаемый под кнопкой.

*Возможно, вы обратили внимание на использование метода JText::_ как в прошлом шаблоне, так и здесь. Это функция, значительно облегчающая перевод компонента. Метод JText::_ ищет текстовую строку в языковом файле компонента и возвращает переведенную строку. Если перевод не найден, функция возвращает строку, переданную ей. Если компонент нужно перевести на другой язык, все, что нужно сделать - создать языковый файл, включающий строки и их перевод на требуемый язык.

Флажки и ссылки

Теперь у нас есть кнопки. Две из этих кнопок управляют существующими записями. Но как узнать, с какими именно записями необходимо работать? Пусть это определит пользователь. Для этого нам нужно добавить флажки в таблицу, чтобы пользователь мог выбрать необходимые записи. Это реализовано в нашем шаблоне.

Для добавления флажков нам необходимо добавить в таблицу дополнительный столбец. Мы добавим столбец между двумя имеющимися.

В заголовке столбца добавим флажок, который можно использовать для выбора или сброса всех флажков:

<th width="20">
    <input type="checkbox" name="toggle" value="" onclick="checkAll(<?php echo count( $this->items ); ?>);" />
</th>

Функция Javascript checkAll встроена в основной пакет Joomla! Javascript, предоставляющий нужную нам функциональность.

Теперь необходимо добавить флажки в каждую строку. У класса JHTML есть метод JHTML::_(), который создаст для нас флажки. Добавим следующие строки в наш цикл:

$checked = JHTML::_('grid.id',   $i, $row->id );

after the line:

$row = $this->items[$i];

Затем добавим ячейку между двумя имеющимися:

<td>
    <?php echo $checked; ?>
</td>

Необходимость выбирать флажок, перемещаться вверх страницы и нажимать кнопку слишком обременительна. Мы добавим ссылку, позволяющую перейти непосредственно к форме редактирования. Следующие строки добавим после вызова метода JHTML::_() для создания ссылки HTML:

$link = JRoute::_( 'index.php?option=com_hello>controller=hello>task=edit>cid[]='. $row->id );

Добавляем ссылку в ячейку, отображая текст:

<td>
    <a href="/<?php echo $link; ?>"><?php echo $row->greeting; ?></a>
</td>

Обратите внимание, что ссылка указывает на контроллер hello. Этот контроллер обработает данные наших приветствий

Если вы помните, у нас были четыре скрытых поля внизу формы. Первое поле носило имя option. Вторым полем является поле task. Оно получает данные в случае нажатия одной из кнопок на панели инструментов. В случае удаления этого поля будет получена ошибка Javascript и кнопки не будут работать. Третье поле - boxchecked. Оно хранит количество отмеченных флажков. Кнопки редактирования и удаления проверяют условие превышения этой величиной нуля, в противном случае не позволяя отправление данных формы. Четвертое поле - это поле контроллера, используемое для определения того, что данные, отправленные из этой формы, будут обработаны контроллером hello.

Вот полный код файла default.php:

<?php 
/**
 * Default admin hello view for Hello World Component
 * 
 * @package    Joomla.Tutorials
 * @subpackage Components
 * @link http://dev.joomla.org/component/option,com_jd-wiki/Itemid,31/id,tutorials:modules/
 * @license        GNU/GPL
 */
defined('_JEXEC') or die('Restricted access');
?>
<form action="index.php" method="post" name="adminForm">
<div id="editcell">
    <table class="adminlist">
    <thead>
        <tr>
            <th width="5">
                <?php echo JText::_( 'ID' ); ?>
            </th>
            <th width="20">   <!-- checkbox to check all items -->
                <input type="checkbox" name="toggle" value="" onclick="checkAll( <?php echo count($this->items); ?> );" /> 
            </th>
            <th>
                <?php echo JText::_( 'Greeting' ); ?>
            </th>
        </tr>            
    </thead>
    <?php
    $k = 0;
    for ($i=0, $n=count( $this->items ); $i < $n; $i++)
    {
        $row = $this->items[$i];
        $checked = JHTML::_('grid.id', $i, $row->id );     //get checkbox HTML
        // get link HTML to edit task for this greeting
        $link = JRoute::_( 'index.php?option=com_hello>controller=hello>task=edit>cid[]='. $row->id );
    ?>
        <tr class="<?php echo "row$k"; ?>">
            <td>
                <?php echo $row->id; ?>
            </td>
            <td>
                 <?php echo $checked; ?> 
            </td>
            <td>
                <a href="/<?php echo $link; ?>"><?php echo $row->greeting; ?></a>
            </td>
        </tr>
    <?php
        $k = 1 - $k;    //switch row class
    }
    ?>
    </table>
</div>
<input type="hidden" name="option" value="com_hello" />
<input type="hidden" name="task" value="" />
<input type="hidden" name="boxchecked" value="0" />
<input type="hidden" name="controller" value="hello" />
</form>

Теперь наше представление hellos закончено. Можно испытывать компонент, чтобы увидеть результаты.

Теперь, когда представление Hellos завершено, время обратить внимание на представление и модель Hello. Настоящая работа выполняется именно здесь.

 

Контроллер Hello

Единственной работой контроллера по умолчанию является отображение представлений.

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

Фактически, добавление и изменение являются одним и тем же заданием: они оба отображают пользователю форму, позволяющую редактировать приветствие. Единственная разница в том, что при создании отображается пустая форма, а при изменении - форма с данными. Поскольку они являются похожими, мы будем выполнять задачу добавления с помощью обработчика задачи изменения. Это указывается в нашем конструкторе:

/**
 * constructor (registers additional tasks to methods)
 * @return void
 */
function __construct()
{
    parent::__construct();
    // Регистрация дополнительных задач 
    $this->registerTask( 'add'  ,     'edit' );
}

Первый параметр JController::registerTask является задачей, второй - метод ее выполнения

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

Наш обработчик задачи изменения выглядит следующим образом:

/**
 * display the edit form
 * @return void
 */
function edit()
{
    JRequest::setVar( 'view', 'hello' );
    JRequest::setVar( 'layout', 'form'  );
    JRequest::setVar('hidemainmenu', 1);
    parent::display();
}

Представление Hello

Представление Hello отображает форму, позволяющую пользователю редактировать приветствие. Метод display должен выполнять несколько простых операций:

  • получить данные из модели
  • создать панель инструментов/div>
  • поместить данные в шаблон
  • вызвать метод display() для отрисовки шаблона

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

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

Также добавим на панель инструментов две кнопки: save и cancel. Функциональность будет практически одинаковой, но в зависимости от текущей задачи отображаться будут разные кнопки. В случае новой записи будет отображаться кнопка cancel, а в случае изменения существующей - кнопка close.

Итак, метод display будет выглядеть так:

/**
 * display method of Hello view
 * @return void
 **/
function display($tpl = null)
{
    //получаем приветствие
    $hello        => $this->get('Data');
    $isNew        = ($hello->id < 1);
    $text = $isNew ? JText::_( 'New' ) : JText::_( 'Edit' );
    JToolBarHelper::title(   JText::_( 'Hello' ).': <small><small>[ ' . $text.' ]</small></small>' );
    JToolBarHelper::save();
    if ($isNew)  {
        JToolBarHelper::cancel();
    } else {
        // для существующих записей кнопка переименовывается на `close`
        JToolBarHelper::cancel( 'cancel', 'Close' );
    }
    $this->assignRef('hello',        $hello);
    parent::display($tpl);
} 

Модель Hello

Для нашего представления необходимы данные. Это значит, что нужно создать соответствующую модель.

У нашей модели будут два свойства: _id и _data. _id будет хранить идентификатор приветствия, data - данные.

Начнем с конструктора, который получает id из запроса:

/**
 * Constructor that retrieves the ID from the request
 *
 * @access    public
 * @return    void
 */
function __construct()
{
    parent::__construct();
    $array = JRequest::getVar('cid',  0, '', 'array');
    $this->setId((int)$array[0]);
}

Метод JRequest::getVar() используется для получения данных из запроса. Первым параметром является имя переменной формы. Второй параметр - значение по умолчанию для присвоения в случае, если значение не найдено. Третий параметр - это имя хэша для получения значения из get, post, и т.д., и последнее значение - тип данных, который следует установить для значения.

Конструктор получит первое значение из массива cid и присвоит его id.

Метод setId() может использоваться для установки id. Изменение id, на которое указывает наша модель, означает, что points указывает на неправильные данные. Следовательно, устанавливая значение id, мы очищаем свойство data:

/**
 * Method to set the hello identifier
 *
 * @access    public
 * @param    int Hello identifier
 * @return    void
 */
function setId($id)
{
    // Устанавливаем id и удаляем данные
    $this->_id        = $id;
    $this->_data    = null;
}

Наконец, нам нужен метод для получения data: getData()

getData проверит, установлено ли значение свойства _data. Если да, он просто возвратит его. В противном случае будут получены данные из базы данных.

/**
 * Method to get a hello
 * @return object with data
 */
function &getData()
{
    // Загружаем данные
    if (empty( $this->_data )) {
        $query = ' SELECT * FROM #__hello '.
                '  WHERE id = '.$this->_id;
        $this->_db->setQuery( $query );
        $this->_data = $this->_db->loadObject();
    }
    if (!$this->_data) {
        $this->_data = new stdClass();
        $this->_data->id = 0;
        $this->_data->greeting = null;
    }
    return $this->_data;
}

Форма

Наконец, все что нам осталось - создать форму для данных. Поскольку мы определили макет как форму, форма будет размещена в файле каталога tmpl представления hello под именем form.php:

<?php defined('_JEXEC') or die('Доступ ограничен!'); ?>
<form action="index.php" method="post" name="adminForm" id="adminForm">
<div class="col100">
    <fieldset class="adminform">
        <legend><?php echo JText::_( 'Details' ); ?></legend>
        <table class="admintable">
        <tr>
            <td width="100" align="right" class="key">
                <label for="greeting">
                    <?php echo JText::_( 'Greeting' ); ?>:
                </label>
            </td>
            <td>
                <input class="text_area" type="text" name="greeting" id="greeting" size="32" maxlength="250" value="<?php echo $this->hello->greeting;?>" />
            </td>
        </tr>
    </table>
    </fieldset>
</div>
<div class="clr"></div>
<input type="hidden" name="option" value="com_hello" />
<input type="hidden" name="id" value="<?php echo $this->hello->id; ?>" />
<input type="hidden" name="task" value="" />
<input type="hidden" name="controller" value="hello" />
</form>

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

Интересная статья? Поделись ей с другими: