Изменим функции генерации и декодирования SEF-ссылок. Откройте файл /components/com_myquestions/router.phpи измените код функции MyQuestionsBuildRoute() следующим образом:
function MyQuestionsBuildRoute(&$query) { $segments = array(); if (isset($query['view'])) { $segments[] = $query['view']; unset($query['view']); } if (isset($query['task'])) { $segments[] = $query['task']; unset($query['task']); } if (isset($query['id'])) { $segments[] = $query['id']; unset($query['id']); } return $segments; }
В том же файле замените функцию MyQuestionsParseRoute() следующей:
function MyQuestionsParseRoute ($segments) { $vars = array(); $vars['view'] = $segments[0]; if (count($segments) > 1) { $vars['task'] = $segments[1]; if (count($segments) > 2) $vars['id'] = $segments[2]; } return $vars; }
Как видите, теперь мы предполагаем, что первый элемент в массиве segments - это view, второй - task, а третий - id.
Добавление контроллера к коду бэкенда
Бэкенд не нуждается в большом контроле над форматом вывода, поэтому его можно не переводить на архитектуру MVC. Добавим только контроллер, чтобы исключить выражение switch().
Создайте файл /administrator/components/com_myquestions/controller.php. В нем мы объявим класс QuestionController. В конструкторе этого контроллера регистрируются задачи, взятые из старого кода переключателя switch из файла admin.myquestions.php.
registerTask('reply', 'replyToQuestion'); $this->registerTask('save', 'saveQuestion'); $this->registerTask('apply', 'saveQuestion'); $this->registerTask('remove', 'removeQuestions'); $this->registerTask('sendToExpert', 'send'); $this->registerTask('sendAnswer', 'send'); $this->registerTask('showCat', 'showCategories'); $this->registerTask('addCat', 'editCategory'); $this->registerTask('editCat', 'editCategory'); $this->registerTask('saveCat', 'saveCategory'); $this->registerTask('applyCat', 'saveCategory'); $this->registerTask('removeCat', 'removeCategories'); } } ?>
Все функции из файла admin.myquestions.phpперейдут в класс QuestionController в качестве методов практически без изменений, за исключением одного аспекта. Отказ от выражения switch ведет к невозможности передавать переменные непосредственно в методы класса контроллера. Поэтому необходимо либо добавлять в класс контроллера новые поля, либо получить переменные из переменных HTTP-запроса или других источников непосредственно в коде каждого метода. В нашем примере почти все методы используют значения переменных option и task. Теперь эти значения будут не передаваться как параметры, а извлекаться из HTTP-запроса с помощью функции JRequest(). Например, первые строки функции saveQuestion() примут вид:
function saveQuestion() { $option = JRequest::getVar('option'); $task = JRequest::getVar('task'); $row = $this->save(); ... }
Итак, перенесите в класс QuestionController функции replyToQuestion(), save(), saveQuestion() и др. Затем замените содержимое файла admin.myquestions.phpследующим кодом:
'showQuestions')); $controller->execute(JRequest::getVar('task')); $controller->redirect(); ?>
Как вы уже заметили, конструктор нашего контроллера в бэкенде имеет параметр default. При вызове конструктора мы передаем в него массив, который хранит значение default_task, равное showQuestions. Таким путем задано название задачи, которая будет выполнена по умолчанию.
Ключевые термины
JController - абстрактный класс для реализации контроллеров. JModel - абстрактный класс для реализации моделей. JView - абстрактный класс для реализации представлений. Регистрация задачи - сопоставление ее какому-либо методу класса, производного от JController.
Краткие итоги
Joomla поддерживает архитектуру MVC для компонентов. Модели, представления и контроллеры реализуются соответственно с помощью абстрактных классов JModel, JView и JController. В компоненте могут быть созданы классы, производные от всех или некоторых из этих классов.
Вот простейшая схема взаимодействия модели, представления и контроллера.
В файле, который находится в корневой папке компонента и называется так же, как компонент, находится код для создания контроллера и вызова его методов execute() и redirect(). Метод execute() вызывает метод контроллера, который называется так же, как и заданная задача.
Класс контроллера, производный от JController, содержит методы для каждой задачи, которую должен выполнять компонент. Метод JController::display(), который вызывается по умолчанию, вызывает методы getView(), getModel(), а также метод display() заданного представления.