Исправим функции вывода нашего компонента так, чтобы они выводили SEF-ссылки вместо обычных. Откройте файл /components/com_myquestions/myquestions.html.phpи измените код функции showCategories() класса HTML_questions следующим образом:
function showCategories($rows, $option) { ?> <p><a href='<?=JRoute::_('index.php?option='.$option.'&task=showlist')?>'> <?=JText::_('COM_MYQUESTIONS_ALL_QUESTIONS')?></a></p> <p><a href='<?=JRoute::_('index.php?option='.$option.'&task=showform')?>'> <?=JText::_('COM_MYQUESTIONS_ADD_QUESTION')?></a></p> <table> <?php foreach($rows as $row) { $link = JRoute::_('index.php?option='.$option.'&id='.$row->id.'&task=showlist'); echo '<tr><td><p><a href="' . $link . '">'.$row->name. '</a></td><td>'.$row->desc.'</td></tr>'; } ?> </table> <?php }
Измените выделенный код в функции HTML_questions::showQuestions():
foreach($rows as $row) { $link = JRoute::_('index.php?option='.$option.'&id='.$row->id.'&task=showquestion'); $link_cat = JRoute::_('index.php?option='.$option.'&id_cat='.$row->id_cat.'&task=showlist'); ?>
Измените также выделенный код в функции HTML_questions::showQuestion():
function showQuestion($row, $option, $row_cat) { $link_cat = JRoute::_('index.php?option='.$option.'&id_cat='.$row->id_cat.'&task=showlist');
Теперь компонент будет генерировать SEF-ссылки по шаблону, установленному в функции MyQuestionsBuildRoute().
Декодирование SEF-ссылок
Если вы сейчас попытаетесь щелкнуть на одной из SEF-ссылок, то получите сообщение:
"Fatal error: Call to undefined function myquestionsParseRoute() in Y:\home\localhost\www\joomla\includes\router.php on line …".
Напишем функцию для декодирования SEF-ссылок.
Откройте файл /components/com_myquestions/router.phpи добавьте следующую функцию:
function MyQuestionsParseRoute ($segments) { $vars = array(); $vars['task'] = @$segments[0]; $vars['id'] = @$segments[1]; return $vars; }
Как видите, в функции MyQuestionsParseRoute() мы считали переменные task и id из массива $segments в том же порядке, в котором мы их записывали в одноименный массив в функции MyQuestionsBuildRoute().
Знаки "@" при получении элементов массива $segments используются для подавления вывода сообщений об обращении к несуществующим элементам массива, т.к. не все наши SEF-ссылки будут содержать id.
Теперь щелкните по какой-либо ссылке во фронтенде и обратите внимание на строку статуса в браузере. Вы должны увидеть URL вида: ссылка: http://localhost/joomla/component/myquestions/showlistили ссылка: http://localhost/joomla/component/myquestions/showquestion/1
Ключевые термины
JDocument - класс для работы с документом. JRoute - класс для создания SEF-ссылок. JUser - класс для работы с данными о пользователе.Документ Документ - буфер, использующийся для хранения содержимого веб-страницы, которая будет показана пользователю после выполнения запроса. Функция генерации SEF-ссылок - функция, которая принимает массив элементов HTTP-запроса и возвращает массив сегментов SEF-ссылки. Функция декодирования SEF-ссылок - функция, которая из массива сегментов SEF-ссылки создает массив переменных HTTP-запроса. Шаблон SEF-ссылок - последовательность сегментов.
Краткие итоги
SEF-ссылки в Joomla создаются с помощью метода JRoute::_(), который переводит внутреннюю ссылку, генерируемую Joomla, в SEF-ссылку. Чтобы компонент работал с SEF-ссылками, сгенерированными по собственному шаблону, необходимо создать в корневой папке его фронтенда файл router.php, в котором должны находиться функция для генерации SEF-ссылок и функция для их декодирования. Эти функции осуществляют взаимно обратные операции: первая из них из массива элементов HTTP-запроса создает массив сегментов SEF-ссылки, а вторая из массива сегментов SEF-ссылки создает массив переменных HTTP-запроса.
Так как SEF-ссылки не позволяют задать названия переменных запроса, то единственный способ определить, к какой переменной относится то или иное значение сегмента, - это использовать шаблон, который задает последовательность сегментов. Шаблон неявно задается в коде каждой из функций в файле router.php.
Для работы с документом и с данными пользователя в Joomla существуют соответственно классы JDocument и JUser.
Вопросы
Какой метод переводит внутреннюю ссылку, генерируемую Joomla, в SEF-ссылку?
Каким образом компоненты работают с SEF-ссылками?
Для чего служат функции генерации и декодирования SEF-ссылок?
Что такое шаблон SEF-ссылок и как он задается?
Какие классы используются для работы с документом и с данными пользователя?
Упражнения
Адаптируйте код из раздела " Практика" для своего варианта (см. список вариантов в дополнительных материалах).
Архитектура MVC в компонентах Joomla
Рассмотрены принципы реализации архитектуры MVC в компоненте и классы Joomla, использующиеся для этого.
Цель лекции:Ознакомиться с основами применения архитектуры MVC при разработке компонентов.
Взаимодействие элементов архитектуры MVC в Joomla
MVC("Model - View - Controller") - это набор паттернов проектирования, который предполагает разделение программного кода на три группы:
модели(model) используются для хранения данных. В Joomla модели реализуются с помощью абстрактного класса JModel;
представления(view) генерируют вывод для заданной информации с помощью шаблона. В Joomla реализуются с помощью абстрактного класса JView;
контроллеры(controller) получают команды от пользователя и управляют моделями и представлениями для выполнения этих команд. В Joomla реализуются с помощью абстрактного класса JController.
Приблизительно схема взаимодействия этих групп в коде Joomla представлена на следующей диаграмме последовательности (рис. 6.1 на основе иллюстрации из книги [4, p.246]).
Рис. 6.1. Взаимодействие контроллера, модели и представления
В файле /components/com_<имя компонента>/<имя компонента>.phpнаходится код для создания контроллера, например:
$controller = new MyComponentController(); $controller->execute(JRequest::getVar('task')); $controller->redirect();
В HTTP-запросе задается задача, представление и, при необходимости, другие данные. Метод execute() вызывает метод вашего контроллера, который называется так же, как и заданная задача. Если задача не указана, то ей будет присвоено значение "display", следовательно, будет выполнен метод display(). Для этой и всех остальных задач, которые должен выполнять ваш компонент, необходимо создать в классе контроллера одноименные методы. Наконец, метод redirect() перенаправляет пользователя к другому URL, если такой URL был задан в каком-либо методе при выполнении контроллера.
В простейшем случае класс контроллера описан в файле /components/com_<имя компонента>/controller.php, в более сложных случаях этих классов может быть несколько. Каждый из них должен быть производным от JController:
class MyComponentController extends JController { … function display() { … parent::display(); … } … }
Вы можете переопределить метод JController::display() в своем классе контроллера. Метод display() базового класса вызывает методы getView(), getModel(), а также метод display() заданного представления. getView() возвращает объект-представитель заданного представления, getModel() - заданной модели. По умолчанию используются те представление и модель, название которых совпадает с именем контроллера.