Уходя от использования роутинга в .htaccess файле, в первую очередь пришёл к стандартному направлению на index.php: разбирал там URL и вызывал соответствующие контроллеры — долгое время был доволен такой техникой. Однако совсем недавно осознал, что что-то делаю не так, что можно сделать эффективнее и лучше.
Далее я расскажу о своём роутинге, использующем XML для хранения правил и в последующем использующем его сериализованный вид.
Уходя от проверки в индексном файле, хотел в первую очередь избавиться от подобной конструкции
if ($url[1] == 'news'){}
Мне не очень хотелось использовать конструкции, предлагаемые большинством фреймворков, в целом выглядящие в таком виде:
$route->addRule(
'/news/{id}/',
array(
'controler' = 'news',
'action' = 'showOne'
)
);
Изначально хотелось хранить правила роутинга в JSON или XML.
Однако парсить каждый раз файл не очень хорошая идея, и такой тип более пригоден для статической навигации или навигации вида /controller/action/.
Мне же хотелось большей гибкости в настройке роутинга и в конечном итоге решил использовать XML для хранения правил, а после парсинга файла и создания массива правил сериализовывать его в файл (в дальнейшем используя его для получения настроек)
XML-файл правил роутинга выглядит примерно так:
<root>
<routes>
<route match="exit" controller="user" action="exit" />
<route match="secret" controller="error" action="404">
<route match="love" controller="secret" action="love" />
</route>
<route match="user" controller="user" action="list">
<route controller="user" action="user" match="{login}">
<route match="comments" controller="user" action="comments" />
<route match="wall" controller="user" action="wall" />
</route>
</route>
</routes>
</root>
Структура правила представляет собой следующее
XML-элемент правил содержится в элементе /root/routes, элемент правил должен содержать в себе следующие атрибуты:
match — Используется для поиска по URL
controller — Вызываемый контроллер
action — Вызываемый метод
match может содержать как статические данные, например «secret», так и динамические «page-{page|num}», динамические отличаются от статических наличием фигурных скобок и названием переменной в ней (название переменной и её значение будут получены в случае совпадения)
В переменной можно указать её тип:
{param1|num} — выдаст совпадение только в случае, если param1 является числовым значением
{param2|str} — выдаст совпадение только в случае, если param2 содержит в себе только буквы и цифры
На основе XML формируется массив, который разделает статические и динамические правила.
Все потомки так же разделяются на статических и динамических.
Так же в элементе /root/system
хранятся следующие данные:
<route match="index" controller="index" action="index" />
<route match="not_found" controller="error" action="404" />
Соответственно в случае, если совпадения по правилам роутинга найдены не будут, вернётся 404 ошибка, в случае пустого урл — его index значение
Использование выглядит так:
$result = $router->get('/secret/love/');
Результат будет таким:
Array
(
[controller] => secret
[action] => love
[values] => Array
(
)
)
$result = $router->get('/user/Testik/wall/');
Array
(
[controller] => user
[action] => wall
[values] => Array
(
[login] => Testik
)
)
Исходники на BitBucket
Скачать zip gz bz2