Печать

Создание MVC компонента Joomla 1.5 - Добавляем действия к Модели

Итак, наш контроллер выполняет только две задачи: создание и изменение. Однако у нас есть кнопки также для сохранения, удаления записей, и отмены. Нужно написать соответствующий код для выполнения этих задач.

Сохранение записи

Следующим шагом логично будет реализовать сохранение записи. Это потребует использование выбора для обработки различных ситуаций, например, различия между созданием новой записи (запрос INSERT), и обновлением существующей записи (запрос UPDATE). Также существует несколько нюансов, связанных с получением данных из формы и помещения их в запрос.

Фреймворк Joomla! облегчает выполнение многих задач. Класс JTable упрощает управление записями в базе данных без необходимости заботится о написании SQL-кода, лежащего в основе этих операций. Он также облегчает перенос данных из HTML-форм в базу данных.

Создание класса Table

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

Вот как выглядит наш класс JTable:

<?php
/**
 * Hello World table class
 * 
 * @package    Joomla.Tutorials
 * @subpackage Components
 * @link http://dev.joomla.org/
 * @license        GNU/GPL
 */
// No direct access
defined('_JEXEC') or die('Доступ ограничен!');
/**
 * Hello Table class
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class TableHello extends JTable
{
    /**
     * Primary Key
     *
     * @var int
     */
    var $id = null;
    /**
     * @var string
     */
    var $greeting = null;
    /**
     * Constructor
     *
     * @param object Database connector object
     */
    function TableHello($db) {
        parent::__construct('#__hello', 'id', $db);
    }
}
?>

Как видите, здесь мы определили два поля: идентификатор и приветствие. Затем был определен конструктор, вызывающий конструктор родительского класса и передающий ему имя таблицы (#__hello), имя поля, являющегося первичным ключом (id), и объект коннектора базы данных.

Этот файл следует назвать hello.php и поместить в каталог tables в администраторском разделе нашего компонента.

Реализация функций в нашей модели

Теперь мы готовы добавить метод в модель для сохранения записи. Назовем этот метод store. Метод store() будет выполнять три вещи: помещать данные из формы в объект TableHello, проверять корректность сформированной записи и сохранять запись в базе данных.

Метод будет выглядеть так:

/**
 * Method to store a record
 *
 * @access    public
 * @return    boolean    True on success
 */
function store()
{
    $row => $this->getTable();
    $data = JRequest::get( 'post' );
    // Bind the form fields to the hello table
    if (!$row->bind($data)) {
        $this->setError($this->_db->getErrorMsg());
        return false;
    }
    // Make sure the hello record is valid
    if (!$row->check()) {
        $this->setError($this->_db->getErrorMsg());
        return false;
    }
    // Store the web link table to the database
    if (!$row->store()) {
        $this->setError($this->_db->getErrorMsg());
        return false;
    }
    return true;
}

Этот метод добавляется в модель hello.

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

Первая строка получает ссылку на объект JTable. Если таблица названа правильно, мы можем не указывать это имя - класс JModel знает, где его искать. Как вы помните, мы назвали наш класс таблицы TableHello и поместили его в файл hello.php в каталоге tables. Если вы следовали этим рекомендациям, класс JModel создаст объект автоматически.

Вторая строка получает данные из формы. Класс JRequest делает эту операцию очень легкой. В данном случае мы получаем все переменные, переданные с помощью метода POST. Они возвращаются в виде ассоциативного массива.

Остальное просто - мы получаем, проверяем и сохраняем. Метод bind() копирует значения из массива в соответствующие свойства объекта таблицы. В данном случае он копирует значения идентификатора и приветствия в объект TableHello.

Метод check() выполняет проверку данных. В классе JTable() этот метод просто возвращает true. Пока он не представляет какого-либо значения, но в будущем он позволит проверять данные с помощью класса TableHello. Этот метод может быть переназначен в классе TableHello методом, выполняющим необходимые проверки.

Метод store() будет помещать данные из объекта в базу данных. Если id равно нулю, будет создана новая запись (INSERT), в противном случае он обновит существующую запись (UPDATE).

Добавление задачи в контроллер

Теперь все готово для добавления задачи в контроллер. Поскольку задача называется save, мы должны назвать метод "save". Это просто:

/**
 * save a record (and redirect to main page)
 * @return void
 */
function save()
{
    $model = $this->getModel('hello');
    if ($model->store()) {
        $msg = JText::_( 'Greeting Saved!' );
    } else {
        $msg = JText::_( 'Error Saving Greeting' );
    }
    // Check the table in so it can be edited.... we are done with it anyway
    $link = 'index.php?option=com_hello';
    $this->setRedirect($link, $msg);
}

Все, что нам нужно - вызвать метод store() модели. Затем следует использовать метод setRedirect() для перенаправления к списку приветствий. Также мы задаем сообщение, которое будет отображено вверху страницы.

Удаление записи

Реализация функции в модели

В модели мы получаем список ID для удаления и вызываем класс JTable для их удаления:

/**
 * Method to delete record(s)
 *
 * @access    public
 * @return    boolean    True on success
 */
function delete()
{
    $cids = JRequest::getVar( 'cid', array(0), 'post', 'array' );
    $row => $this->getTable();
    foreach($cids as $cid) {
        if (!$row->delete( $cid )) {
            $this->setError( $row->getErrorMsg() );
            return false;
        }
    }                        
    return true;
}

Мы вызываем метод JRequest::getVar() для получения данных из запроса, затем вызываем метод delete() для удаления каждой строки. Сохраняя ошибки в модели, мы обеспечиваем возможность получить их позже, если потребуется.

Выполнение задачи удаления в контроллере

Это очень похоже на метод save(), выполняющий сохранение:

/**
 * remove record(s)
 * @return void
 */
function remove()
{
    $model = $this->getModel('hello');
    if(!$model->delete()) {
        $msg = JText::_( 'Error: One or More Greetings Could not be Deleted' );
    } else {
        $msg = JText::_( 'Greeting(s) Deleted' );
    }
    $this->setRedirect( 'index.php?option=com_hello', $msg );
}

Отмена операции редактирования

Все, что нужно для прерывания операции редактирования - перенаправление на главное представление:

/**
 * cancel editing a record
 * @return void
 */
function cancel()
{
    $msg = JText::_( 'Operation Cancelled' );
    $this->setRedirect( 'index.php?option=com_hello', $msg );
}

Заключение

Мы реализовали простой механизм для нашего компонента. Теперь у нас есть возможность редактировать элементы, отображаемые в представлении. Мы продемонстрировали взаимодействие между моделями, представлениями и контроллерами. Также мы показали, как класс JTable можно расширить для предоставления простого доступа к таблицам в базе данных. Также можно увидеть использование класса JToolBarHelper для создание панелей кнопок в компоненте для предоставления стандартного вида для различных компонентов.

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