Объектом стал сам роутер, а средвом маршруты.
Возможные варианты хранения:
YAML
+ Интуитивый
— Требуется кеширования (для повышения производительности)
— Требуется библиотека для парсинга (минус, поскольку в случаях лицензирования могут возникнуть трудности)
ini
+ Быстрый парсинг php
+ Отсутствие потребности в библиотеках
— Желательно все-же кешировать
— Далеко не интуитивный
PHP-file
Вот мы и подошли к самому важному. Но вопрос все же остается. Как хранить его?
$routes = array(); $routes['routeName'] = array( 'pattern' => '/my/home/page', 'controller' => 'homepage', 'action' => 'show' );
Вариант? Но ведь не интуитивно. И не удобно считывать будет с такого файла, и многомерные массивы.
Да и вдруг кто-то случайно напишет не controller, a controIler. (Маленькая l и большая I соответственно). Ну случайно. Допустим. Ну ведь не будет работать.
Или вариант, который я встречал не реже:
$router = new Router(); $route = new Route('RouteName', array('controller' => 'mycontroller', 'action' => 'myaction')); $router->addRoute($route);
Находим файл router.php и берем оттуда $router. Удобно? Я сомневаюсь.
Решение
Моя идея заключается в создании класса конфигурации в стиле PHP5.
Пример:
<?php namespace Сonfig; use Routing\Route; class Routes { function welcome() { //название функции и есть названием маршрута $a = new Route; $a->setPattern('/') ->setController('hello') ->setAction('welcome') ->setFormat('html'); return $a; } function main() { $a = new Route; $a->setPattern('/home/{user}') ->setController('controller') ->setAction('list') ->setFormat('html'); return $a; } }
<?php namespace Routing; class Route { private $pattern = null, $controller = null, $action = null, $parameters = array(), $regexp = null, $format = 'html'; public function setPattern($pattern) { $this->regexp = str_replace('/', '\/', $pattern); $this->regexp = preg_replace('/\{\w+\}/', '(\w+)', $this->regexp); $this->regexp = "/^{$this->regexp}$/i"; $this->pattern = $pattern; return $this; } public function getPattern() { return $this->pattern; } public function setController($controller) { $this->controller = $controller; return $this; } public function getController() { return $this->controller; } public function setAction($action) { $this->action = $action; return $this; } public function getAction() { return $this->action; } public function addParameter($name, $value) { $this->parameters[$name] = $value; return $this; } public function getParameters() { return $this->parameters; } public function getRegexp() { return $this->regexp; } public function setFormat($format) { $this->format = $format; return $this; } public function getFormat() { return $this->format; } public function isValid() { if(is_null($this->getPattern()) ||is_null($this->getController()) ||is_null($this->getAction()) ) return false; return true; } }
Для обработки взятых паттернов с маршрута я использую регулярные выражения.
<?php namespace Routing; use \Routing\Exception\Route as RouteException; class Router { protected $routes = array(), $address = null; public function __construct($str){ $this->address = $str; } public function init(){ $routes = new \Config\Routes; $resRoute = null; foreach(get_class_methods($routes) as $route) { if(!is_callable(array($routes, $route))) { throw new RouteException('All routes must be public.'); } $route = call_user_func(array($routes, "$route")); if(!$route->isValid()) { throw new RouteException('Invalid route found.'); } $params = array(); if(preg_match($route->getRegexp(), $this->address, $params)) { if(count($params) == 0) { $resRoute = $route; break; } $input = array(); preg_match('/\{(\w+)\}/', $route->getPattern(), $input); for($i=1; $i< count($input); $i++) { $route->addParameter($input[$i], $params[$i]); } $resRoute = $route; break; } } if(is_null($resRoute)) { throw new RouteException('404', 404); } return $resRoute; } }
В результате алгоритм работы получается такой:
- Получаем текущую строку адресу
- Ищем шаблон, который подходит под данный адрес
- В случае если шаблон содержит параметры, добавляем их в маршрут
- Возвращаем маршрут
Сейчас меня не устраивает только парсинг паттернов в regexp’ы.
Буду рад услышать ваши идеи и критику.
Спасибо.
ссылка на оригинал статьи http://habrahabr.ru/post/175621/
Добавить комментарий