Вольный перевод официальной документации.
Компонент маршрутизации связывает HTTP запрос с набором заранее сконфигурированных данных.
Установка
Вы можете установить компонент двумя способами:
- Через Composer (symfony/routing – проект packagist.org)
- Используя официальный Git репозиторий (https://github.com/symfony/routing)
Затем, подключить автозагрузчик vendor/autoload.php, который предоставляет Composer. Иначе, ваше приложение не сможет найти необходимые для компонента классы.
Использование
Для развертывания системы маршрутизации, вам понадобится три класса:
- RouteCollection, который содержит описание маршрутов (экземпляры класса Route).
- RequestContext, — в нем информация о текущем запросе.
- UrlMatcher, — непосредственно связывает запрос, с заранее описанным маршрутом.
Простой пример. Предполагается, что вы уже сконфигурировали автолоадер, для загрузки классов компонента Routing.
use Symfony\Component\Routing\Matcher\UrlMatcher; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $route = new Route('/foo', array('_controller' => 'MyController')); $routes = new RouteCollection(); $routes->add('route_name', $route); $context = new RequestContext('/'); $matcher = new UrlMatcher($routes, $context); $parameters = $matcher->match('/foo'); // array('_controller' => 'MyController', '_route' => 'route_name')
Параметры для RequestContext могут быть взяты из суперглобальной переменной $_SERVER, но проще воспользоваться компонентом HttpFoundation. Как это сделать, объясняется ниже.
Вы можете добавлять столько маршрутов в коллекцию RouteCollection, сколько захотите.
Метод RouteCollection::add() принимает два аргумента. Первый – название маршрута, второй – экземпляр класса Route. В конструктор Route, передается URL и массив с некоторыми данными, которые могут быть любыми, в зависимости от вашего приложения. Они будут возвращены при совпадении маршрута с текущим URL запроса.
UrlMatcher::match() – возвращает вышеупомянутые данные, вместе с плейсхолдерами (см. ниже). Ваше приложение может использовать их, для дальнейшей обработки запроса. В дополнение, к массиву данных, добавляется ключ _route, с именем совпавшего маршрута.
Если ни один из маршрутов не подходит для текущего запроса, выбрасывается исключение ResourceNotFoundException.
Определение (описание) маршрутов.
Полное описание маршрута содержит до семи составляющих.
- URL запроса. Он сравнивается с URL, переданным в RequestContext, и может содержать именованные плейсхолдеры (например, {placeholders}) для сравнения динамических частей урла.
- Массив значений по умолчанию. Некоторые данные, которые будут возвращены для найденного роута.
- Массив с обязательными параметрами. Проверяет значения (обычно часть URL) по шаблону, на базе регулярных выражений.
- Массив с настройками. В нем внутренние параметры для роута. Используется редко.
- Имя хоста. Сравнивается со значением из запроса. Смотрите статью «поиск маршрутов по хосту».
- Массив со схемами. Определяет конкретную HTTP схему: http или https.
- Массив с методами. Содержит конкретные методы HTTP запросов (HEAD, GET, POST, … )
Взгляните на следующий пример, который сочетает в себе некоторые из описанных идей:
$route = new Route( '/archive/{month}', // path array('_controller' => 'showArchive'), // default values // requirements array('month' => '[0-9]{4}-[0-9]{2}', 'subdomain' => 'www|m'), array(), // options '{subdomain}.example.com', // host array(), // schemes array() // methods ); // ... $parameters = $matcher->match('/archive/2012-01'); // array( // '_controller' => 'showArchive', // 'month' => '2012-01', // 'subdomain' => 'www', // '_route' => ... // ) $parameters = $matcher->match('/archive/foo'); // throws ResourceNotFoundException
В данном примере, найден маршрут /archive/2012-01, потому что регулярное выражение шаблона совпало с запросом. Для /archive/foo совпадений не нашлось, исходя из той же логики.
Когда используются шаблоны, при вызове match в возвращаемом массиве оказывается часть совпавшего урла.
$route = new Route( '/start/{suffix}', array('suffix' => ''), array('suffix' => '.*') );
Использование префиксов
Существует возможность добавлять коллекции RouteCollection друг в друга. Таким образом, получается дерево маршрутов. В дополнение вы можете определить для поддеревьев префикс и значения по умолчанию: переменных, обязательных параметров, настроек, схем соединения и хоста через методы класса RouteCollection.
$rootCollection = new RouteCollection(); $subCollection = new RouteCollection(); $subCollection->add(...); $subCollection->add(...); $subCollection->addPrefix('/prefix'); $subCollection->addDefaults(array(...)); $subCollection->addRequirements(array(...)); $subCollection->addOptions(array(...)); $subCollection->setHost('admin.example.com'); $subCollection->setMethods(array('POST')); $subCollection->setSchemes(array('https')); $rootCollection->addCollection($subCollection);
Установка параметров запроса
RequestContext — предоставляет информацию о текущем запросе. Вы можете определить все параметры HTTP запроса для этого класса, через его конструктор:
public function __construct( $baseUrl = '', $method = 'GET', $host = 'localhost', $scheme = 'http', $httpPort = 80, $httpsPort = 443, $path = '/', $queryString = '' )
В общем случае, можно передать значения из массива $_SERVER в RequestContext. Но если вы установили компонент HttpFoundation, просто передайте экземпляр класса Request:
use Symfony\Component\HttpFoundation\Request; $context = new RequestContext(); $context->fromRequest(Request::createFromGlobals());
Более подробная информация о компоненте HttpFoundation.
Генерация URL на базе роута.
В то время, как задача UrlMatcher найти маршрут, соответствующий текущему запросу, вы так же можете произвести обратную операцию — сгенерировать URL на базе определенного маршрута:
use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; $routes = new RouteCollection(); $routes->add('show_post', new Route('/show/{slug}')); $context = new RequestContext('/'); $generator = new UrlGenerator($routes, $context); $url = $generator->generate('show_post', array( 'slug' => 'my-blog-post', )); // /show/my-blog-post
Если была указана схема (http, https), то будет сгенерирован абсолютный URL, но лишь в том случае если схема текущего запроса в RequestContext отличается.
Загрузка маршрутов из файла
Вы уже убедились, насколько легко добавлять маршруты в коллекцию прямо в PHP скрипте. Однако, существует возможность их загрузки из различных типов файлов.
Компонент Routing поставляется вместе с классами-загрузчиками, каждый из которых дает возможность загрузить коллекцию маршрутов из внешнего файла, определенного формата. Каждому загрузчику следует передать экземпляр FileLocator, в качестве аргуметна конструктора. Вы можете использовать FileLocator для определения (создания) массива путей, по которым загрузчик будет искать запрошенный файл. Если таковой будет найден, загрузчик вернет объект RouteCollection.
К примеру, если используется загрузчик YamlFileLoader, описание маршрутов будет выглядеть так:
# routes.yml route1: path: /foo defaults: { _controller: 'MyController::fooAction' } route2: path: /foo/bar defaults: { _controller: 'MyController::foobarAction' } |
Для загрузки вышеозначенного файла, используется нижеследующий код. Подразумевается, что ваш routes.yml находится в той же директории, что и скрипт:
use Symfony\Component\Config\FileLocator; use Symfony\Component\Routing\Loader\YamlFileLoader; // look inside *this* directory $locator = new FileLocator(array(__DIR__)); $loader = new YamlFileLoader($locator); $collection = $loader->load('routes.yml');
Кроме YamlFileLoader, есть еще два загрузчика, которые работают по тому же принципу:
- XmlFileLoader
- PhpFileLoader
Если вы выберите PhpFileLoader, необходимо указать имя PHP файла, который вернет RouteCollection:
// RouteProvider.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add( 'route_name', new Route('/foo', array('_controller' => 'ExampleController')) ); // ... return $collection;
Описание маршрутов через замыкания (Closures)
Так же присутствует ClosureLoader, он вызывает замыкание, и использует результат в качестве RouteCollection:
use Symfony\Component\Routing\Loader\ClosureLoader; $closure = function () { return new RouteCollection(); }; $loader = new ClosureLoader(); $collection = $loader->load($closure);
Описание маршрутов через аннотации
Последний, но не менее интересный тип – AnnotationDirectoryLoader и AnnotationFileLoader, для загрузки маршрутов из аннотаций классов. Описание указанных загрузчиков отсутствует в данной статье.
Универсальный класс Route
Route, является универсальным классом, который позволяет удобно использовать компонент Routing. Его конструктор предполагает в качестве аргументов — экземпляр загрузчика, путь к файлу с маршрутами, и еще некоторые параметры:
public function __construct( LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null, LoggerInterface $logger = null );
С помощью опции cache_dir, включается кэширование маршрутов (в том случае если передан путь), или выключается (если он установлен в null). Кэширование происходит автоматически и в «фоновом режиме». Пример кода, в данном случае, будет таким:
$locator = new FileLocator(array(__DIR__)); $requestContext = new RequestContext('/'); $router = new Router( new YamlFileLoader($locator), 'routes.yml', array('cache_dir' => __DIR__.'/cache'), $requestContext ); $router->match('/foo/bar');
При использовании кэширования, компонент Routing компилирует классы и сохраняет их в cache_dir. Ваш скрипт должен обладать правами записи в эту директорию.
Поддержка юникода (UTF-8)
Начиная с Symfony 3.2 включена поддержка UTF-8 для маршрутов и обязательных параметров.
Благодаря параметру utf8, компонент Routing поддерживает соответствующую кодировку:
// app/config/routing.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('route1', new Route('/category/{name}', array( '_controller' => 'AppBundle:Default:category', ), array(), array( 'utf8' => true, ) ); // ... return $collection;
В примере, параметр utf8 установлен в значение true, что сообщает Symfony считать «.» любым символом UTF-8, вместо однобайтовых. То есть, запрос /category/日本語 будут совпадать с маршрутом. Если интересно, при включенном параметре, так же поддерживаются символы эмоций в URL.
Аналогичным образом можно использовать UTF-8 в шаблонах:
// app/config/routing.php use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; $collection = new RouteCollection(); $collection->add('route2', new Route('/default/{default}', array( '_controller' => 'AppBundle:Default:default', ), array( 'default' => '한국어', ), array( 'utf8' => true, ) ); // ... return $collection;
root4root aka admin
Добавить комментарий
X