Всем доброго времени суток. Сегодня мы будем разбирать довольно сложную часть реализации роутинга в CMS RS-MINI. Нам предстоит обработать контроллеры для конечной страницы и поместить объекты этих контроллеров в специальный массив. Какие операции входят в понятие «сборка контроллеров»?
Те объекты контроллеров которые имеются у нас сейчас, лишь хранилище информации для роутинга системы. Используя эту информацию наш роутинг должен поднять объекты контроллеров которые будут храниться в папке с модулями. Давайте для удобство дадим термины этим двум видам контроллеров:
Теперь проще будет говорить про какой вид контроллера я говорю
Я немного отвлекся... Так в чем конкретная суть метода controllerRun()? Метод должен будет
Сборка массива runList первостепенная задача на сегодня. На этом логика метода не закончится. Мы как минимум еще две статьи будем работать только с этим методом. Я специально разбил материал на части, для лучшего восприятия кода (надеюсь поэтапная реализация этого метода улучшит его понимание)
Пожалуй пришло время создать наш первый модуль (пока что тестовый). Заходим в папку /project/modules/pub/ и создаем в нем папку test. В папке /project/modules/pub/test/ нужно создать три каталога:
Это три основных папки каждого модуля. Будут еще папки, но я пока не определился какие именно.
Теперь заходим в папку /project/modules/pub/test/controller/ и создаем там файл с именем intro.class.php с вот таким кодом внутри:
<?php
/*
* @package RS-MINI
* @copyright (c) 2015 Alexey Glumov aka Rio-Shaman (support@rio-shaman.ru)
* @license GNU General Public License version 2; see LICENSE.txt
*
*/
namespace pub\test\controller;
if(!defined('RS-MINI')) die();
/*
* intro v 1.0
*
* контроллер модуля pub.test
*
*/
class intro extends \core\abstractcontroller
{
/*
* запуск контроллера
*
* @access - public
* @return - true или false (404 ошибка)
*
*/
public function run()
{
return TRUE;
}
}
Это минимальный код контроллера модуля. Тут пока пояснять нечего, ведь контроллер пуст. Правда есть один нюанс касающийся метода run(). Если Вы помните, в абстрактном классе abstractcontroller.class.php уже существует метод run(). Может возникнуть вопрос, зачем в базовом коде (в минимальном коде) контроллера описывается метод run(), ведь он уже существует? Ответ прост, в абстрактном классе, метод run() возвращает false, что должно будет привести к 404-ой ошибке. В коде основного контроллера метод run() возвращает true, что предотвратит появление ошибки.
Ну что же, пора опубликовать код метода. Каждая строчка задокументирована + есть некоторые пояснения в самой статье, по тому считаю, что код должен вызывать минимум вопросов.
Вот код метода: (метод находится в классе application.class.php который лежит в папке /rs-mini/core/)
/*
* метод стартует контроллеры
*
* @access - private
*
*/
private static function controllerRun()
{
// массив с контроллерами которые необходимо будет запустить
$runList = array();
// листаем страницы
foreach (self::$map->pageList as $key => $page) {
// список блоков контроллеров
$blockList = array(
'top',
'center',
'bottom'
);
// если на странице контроллеры
if ($page->controllerList) {
// листаем все возможные блоки
foreach ($blockList as $blockAlias) {
// листаем контроллеры страницы
foreach ($page->controllerList as $block => $controllerList) {
// если листаемый блок совпадает с блоком контроллеров страницы - то разбираем контроллеры данного блока
if ($blockAlias == $block) {
// сначало проглядываем наследуемые контроллеры (потом подключенные на прямую)
for ($inh = 0; $inh <= 1; $inh++) {
// листаем контроллеры
foreach ($controllerList as $controller) {
// проверка наследия (первая итерация ищет только наследованные контроллры)
// при $inh == 0 запускаются только унаследованные контроллеры
// при $inh == 1 запускаются подключенные на прямую
if ($controller->inheritFlag != ( ($inh == 0) ? TRUE : FALSE ))
continue;
// пропускаем отключенные контроллеры
if ($controller->getParam('active') == 'disable')
continue;
// подставляем в путь допол. папку
// бьем имя контроллера на массив
$controllerClass = explode('.', $controller->controllerName);
// отрезаем два первых элемента массива
$controllerSlice = array_slice($controllerClass, 2);
// во второй элемент массива вставляем слово controller
$controllerClass[2] = 'controller';
// вертаем в массив оставшие элементы после отработки функции array_slice
for ($i = 0; isset($controllerSlice[$i]); $i++)
$controllerClass[($i + 3)] = $controllerSlice[$i];
// тем самым получаем полный путь к классу
// пример: было pub.test.intro а стало pub\test\controller\intro
$controllerClass = implode('\\', $controllerClass);
// записываем в параметры инфу о странице
$controller
->setParam('page_id', $page->pageID)
->setParam('page_alias', $page->pageAlias)
->setParam('page_parent', $page->pageParent)
;
// создаем объект контроллера
$obj = new $controllerClass(self::$dom, $controller->getParams());
// регистрируем динамичный алиас и его значение в
// статичном свойстве абстрактного класса контроллера
// если реальный алиас страницы row_id а в адресную строку было вбито
// /123/ то в свойстве dynamicValue абстракного класса abstractcontroller
// будет зарегистрирован ключ row_id с значением 123
// dynamicValue['row_id'] = '123'
if ($page->pageType == 'dynamic')
$obj->setDynamicValue($page->pageDynamicAlias, $page->pageAlias);
// проверяем на валидацию
if (!$obj->validate())
self::notFound();
// если листается последняя страница
if ($key == (count(self::$map->pageList) - 1))
// сохраняем данные для запуска
$runList[] = array(
'obj' => $obj,
'controller' => $controller
);
}
}
}
}
}
}
}
// тест работы роутинга
// просматриваем массив объектов для запуска
?><xmp><?
var_dump($runList);
?></xmp><?
}
Вы могли заметить, что в конце метода есть строки для тестирования. Что бы увидеть результат, необходимо вызвать этот метод в методе run() класса application.class.php. (код пишется там же)
/*
* главный метод. запуск системы
*
* @access - public
*
*/
public static function run()
{
// поднимаем некоторые классы ядра
// объект по работе с структурой сайта
self::$map = new map();
// объект прослойка между контроллерами и вьюшкой
self::$dom = new dom();
// стартуем подключение к БД
sql::setConnect();
// получаем открываемую страницу
if (!self::$map->getPage())
self::notFound();
// мероприятия по объеденению унаследованных контроллеров с конечной страницей
self::unionRun();
// запускаем контроллеры
self::controllerRun();
}
Если сейчас перейти по адресу http://mini.test.ru/about/ то мы увидим не маленький дамп массива runList. Из всего дампа, на данном этапе, нам важно увидеть вот эту строчку
которая говорит нам о том, что на основе хранилище контроллера поднялся объект основного контроллера pub.test.intro.
Если у Вас есть какие-либо вопросы, пишите их в комментариях. Результат проделанной работы, Вы как всегда можете скачать в конце статьи.
Всего Вам наилучшего, на сегодня все!