
- •Что в этой книге
- •Настройки против Расширений
- •Как расширить Joomla!
- •Компоненты (Components)
- •Модули (Modules)
- •Плагины (Plug-Ins)
- •Обзор тем
- •Создание пи (Toolbars) и Списков
- •Поддержание стиля и исключение повторений кода используя html функции
- •Доступ к бд и управление записями
- •Безопасность и предпочтительный способ получения переменных запроса
- •Меню управления
- •Управления логикой работы внутри Компонента
- •Конфигурация посредством xml-параметров
- •Упаковка и распространение
- •Наш Проект для примера
- •Приступая к разработке Компонента
- •Структура Компонента Joomla!
- •Запуск Компонента
- •Разделение на иа и ип в Joomla
- •Регистрация Компонента в бд
- •Создание пи
- •Доступные кнопки пи
- •Создание таблицы бд
- •Создание класса Table
- •Создание формы Обзора
- •Обработка данных
- •Создание Списка
- •Редактирование записей
- •Удаление записей
- •Разработка ип
- •Листинг Обзоров
- •Отображение Обзора
- •Генерация дружественных для поисковиков ссылок
- •Создание url сегментов
- •Парсинг url сегментов
- •Добавление комментариев
- •Отображение комментариев
- •Разработка Модуля
- •Регистрация Модуля в бд
- •Создание и настройка базового Модуля
- •Воспользуемся некоторыми помощниками (class Helper)
- •Пробуем различные стили
- •Попробуем смешать
- •Расширяем проект
- •Модель, Вид, Контроллер: Почему?
- •Построение Модели данных
- •Модель Все Обзоры
- •Модель одиночного Обзора
- •Миграция на Виды
- •Переключения посредством Контроллеров (Controllers)
- •Обновление связей и маршрутов
- •Реорганизация кода иа
- •Управление публикацией Обзоров
- •Добавление постраничной навигации
- •Управление Коментариями
- •Дополнительные пи
- •За кулисами: Плагины (Plug-Ins)
- •Запросы к бд
- •Плагин ссылка
- •Плагин справочной информации
- •Поиск Обзоров
- •Параметры
- •Добавление параметров к расширениям
- •Параметры для Модулей
- •Параметры для Плагинов
- •Параметры для Компонентов
- •Упаковываем все вместе
- •Список всех файлов
- •Упаковка Модуля
- •Упаковка Плагина
- •Упаковка Компонента
- •Включение sql-запросов
- •Создание пунктов меню иа
- •Дополнительные сценарии установки
- •Распространение
- •Содержание
Обновление связей и маршрутов
В связи с изменениями в архитектуре нашего Компонента, мы должны внести некоторые изменения в код написанный ранее в Модуле. Необходимо указать Вид Обзора в создаваемых ссылках. В /modules/mod_reviews/helper.php, замените строку с $link на такую:
$link = JRoute::_("index.php?option=com_reviews&view=review&id=" .
$review->id);
Далее, нам необходимо обновить маршрутизатор для использования переменной Вида при построении и анализе ссылок. Откройте
/components/com_reviews/router.php и измените (как выделено) код ReviewsBuildRoute(), который ранее обрабатывал задачу (task):
function ReviewsBuildRoute(&$query)
{
$segments = array();
if (isset($query['view'])) {
$segments[] = $query['view'];
unset($query['view']);
}
if(isset($query['id']))
{
$segments[] = $query['id'];
unset($query['id']);
}
return $segments;
}
Так как мы больше не используется в нашей задаче навигационные ссылки, больше нет нужды подключать создание или разбора SEF URL. Для обновления ReviewsBuildRoute() достаточно просто заменить task на view. Однако, ReviewsParseRoute() потребуется немного переписать, потому что сейчас мы могли бы иметь 0, 1 или 2 дополнительных сегментов, а не только 0 или 2. Вид all не сопровождается id, поэтому нам нужно настроить парсер для подсчета сегментов, прежде чем пытаться установить их оба view и id. Замените ReviewsParseRoute() на такой код:
function ReviewsParseRoute($segments)
{
$vars = array();
$vars['view'] = $segments[0];
if (count($segments) > 1)
{
$vars['id'] = $segments[1];
}
return $vars;
}
В этой версии функции, мы инициализируем массив $vars, а затем присваиваем $vars['view'] первому элементу $segments. Если есть более одного элемента в $segments, считаем, что второй это id и присваиваем $vars['id'] его значение. Наконец, мы возвращаем $vars.
Наши ссылки на листинг Обзоров будут выглядеть так:
http://www.oursite.com/reviews/all, в то время как ссылки на отдельные Обзоры будут выглядеть так:
http://www.oursite.com/reviews/review/2.
Реорганизация кода иа
Использование Контроллера также благоприятно скажется на код для ИА, который мы создали в главе 3. Мы можем повторно использовать большую часть существующего кода, если откажемся от поддержки switch().
В /administrator/components/com_reviews создайте файл controller.php с таким кодом:
defined( '_JEXEC' ) or die( 'Restricted access' );
jimport( 'joomla.application.component.controller' );
class ReviewController extends JController
{
function __construct( $default = array() )
{
parent::__construct( $default );
$this->registerTask( 'add' , 'edit' );
$this->registerTask( 'apply', 'save' );
}
function edit()
{
global $option;
$row =& JTable::getInstance('review', 'Table');
$cid = JRequest::getVar( 'cid', array(0), '', 'array' );
$id = $cid[0];
$row->load($id);
$lists = array();
$reservations = array(
'0' => array('value' => 'None Taken',
'text' => 'None Taken'),
'1' => array('value' => 'Accepted',
'text' => 'Accepted'),
'2' => array('value' => 'Suggested',
'text' => 'Suggested'),
'3' => array('value' => 'Required',
'text' => 'Required'),
);
$lists['reservations'] = JHTML::_('select.genericlist',
$reservations, 'reservations', 'class="inputbox" '. '',
'value', 'text', $row->reservations );
$lists['smoking'] = JHTML::_('select.booleanlist', 'smoking',
'class="inputbox"', $row->smoking);
$lists['published'] = JHTML::_('select.booleanlist', 'published',
'class="inputbox"', $row->published);
HTML_reviews::editReview($row, $lists, $option);
}
function save()
{
global $option;
$row =& JTable::getInstance('review', 'Table');
if (!$row->bind(JRequest::get('post')))
{
echo "<script> alert('".$row->getError()."');
window.history.go(-1); </script>\n";
exit();
}
$row->quicktake = JRequest::getVar( 'quicktake', '', 'post',
'string', JREQUEST_ALLOWRAW );
$row->review = JRequest::getVar( 'review', '', 'post',
'string', JREQUEST_ALLOWRAW );
if(!$row->review_date)
$row->review_date = date( 'Y-m-d H:i:s' );
if (!$row->store()) {
echo "<script> alert('".$row->getError()."'); window.history.
go(-1); </script>\n";
exit();
}
switch ($this->_task)
{
case 'apply':
$msg = 'Changes to Review saved';
$link = 'index.php?option=' . $option .
'&task=edit&cid[]='. $row->id;
break;
case 'save':
default:
$msg = 'Review Saved';
$link = 'index.php?option=' . $option;
break;
}
$this->setRedirect($link, $msg);
}
function showReviews()
{
global $option;
$db =& JFactory::getDBO();
$query = "SELECT * FROM #__reviews";
$db->setQuery( $query );
$rows = $db->loadObjectList();
if ($db->getErrorNum()) {
echo $db->stderr();
return false;
}
HTML_reviews::showReviews( $option, $rows );
}
function remove()
{
global $option;
$cid = JRequest::getVar( 'cid', array(), '', 'array' );
$db =& JFactory::getDBO();
if(count($cid))
{
$cids = implode( ',', $cid );
$query = "DELETE FROM #__reviews WHERE id IN ( $cids )";
$db->setQuery( $query );
if (!$db->query()) {
echo "<script> alert('".$db->getErrorMsg()."'); window.
history.go(-1); </script>\n";
}
}
$this->setRedirect( 'index.php?option=' . $option );
}
}
Этот Контроллер переопределяет конструктор, регистрирует дополнительную задачу edit(), и фиксирует изменения в save(). При вызове save() проверяется $this->_task чтобы выяснить, какую задачу обрабатывает функции, а также использовать информацию для перенаправления пользователей.
На данный момент, решено оставить текущий файл admin.reviews.html.php без изменений для перехода на Виды. В ИА Виды менее полезны, чем в ИП. ИА не нуждается в обширном контроле за выходным форматом.
Теперь необходимо изменить admin.reviews.php для использования Контроллера. Откройте его и замените код на следующий:
<?php
defined( '_JEXEC' ) or die( 'Restricted access' );
require_once( JApplicationHelper::getPath( 'admin_html' ) );
require_once( JPATH_COMPONENT.DS.'controller.php' );
JTable::addIncludePath(JPATH_COMPONENT.DS.'tables');
$controller = new ReviewController(
array('default_task' => 'showReviews') );
$controller->execute( JRequest::getVar( 'task' ) );
$controller->redirect();
?>
Обратите внимание, что мы уже встроили массив в Контроллер конструктора. Этот массив имеет значение для default_task, что позволяет нам указать Контроллеру вызвать showReviews() вместо того чтобы искать display(). В отличие от старого переключателя [switch(). прим.переводчика], мы не в состоянии передать переменные непосредственно в функции Контроллера. При необходимости, можно добавить переменные к Контроллеру. Однако большинство переменных доступны через функции JFactory, глобальные объекты, или из переменных HTTP запроса.
После того как все наши файлы на месте и задача по умолчанию назначена, вызываем функцию execute() Контроллера, для выполнения соответствующих действий. Мы присваиваем переменной task значение, чтобы сообщить Контроллеру функцию вызова. Если ни одна функция не определена в task Контроллер выполняет задачу по умолчанию. После завершения $controller->execute(), мы используем функцию redirect(), чтобы перенаправить пользователя на любой URL установленный setRedirect(). Такая конструкция позволяет нашим функциям указывать конечный URL назначения без труда и прямо сейчас. При необходимости, мы можем выполнить действие "очистить" после того, как Контроллер отработает, а затем выполнить редирект [переход по определенному адресу. прим.переводчика]