Компонент Routing
Дата оновлення перекладу 2023-05-19
Компонент Routing
Компонент Routing з'єднує HTTP-запит з набором змінних конфігурації.
Установка
1
$ composer require symfony/routing
Також ви можете клонувати репозиторій https://github.com/symfony/routing.
Note
Якщо ви встановлюєте цей компонент поза додатком Symfony, вам потрібно підключити
файл vendor/autoload.php
у вашому коді для включення механізму автозавантаження
класів, наданих Composer. Детальніше можна прочитати у цій статті.
Використання
See also
Ця стаття пояснює як використовувати функції Маршрутизатору у якості незалежного компоненту в будь-якому додатку PHP. Прочитайте статтю Routing для розуміння, як використовувати його в додатках Symfony.
Для того, щоб встановити базову систему маршрутизації, вам необхідні три складові:
- RouteCollection, який містить визначення маршрутів (екземпляри класу Route)
- RequestContext, який містить інформацію про запит
- UrlMatcher, який виконує з'єднання запиту з єдиним маршрутом
Ось швидкий приклад. Відмітьте, що передбачається, що ви вже сконфігурували ваш автозавантажувач, щоб він завантажував компонент Routing:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
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');
// масив ('_controller' => 'MyController', '_route' => 'route_name')
Note
Параметри RequestContext можуть бути наповнені
значеннями, що зберігаються в $_SERVER
, але легше використовувати компонент
HttpFoundation, як пояснюється нижче.
Ви можете додавати до RouteCollection стільки маршрутів, скільки хочете.
Метод RouteCollection::add() бере два аргументи. Перший - це ім'я маршруту. Другий - об'єкт Route, який очікує URL-шлях і деякий масив користувацьких змінних в своєму конструкторі. Цей масив користувацьких змінних може бути чим завгодно важливим для вашого додатку, і повертатися при співстваленні маршруту.
UrlMatcher::match()
повертає змінні, які ви встановили в маршруті, а також рандомні заповнювачі
(див. нижче). Тепер ваш застосунок може використовувати цю інформацію, щоб продовжувати
обробку запиту. На додаток до сконфігурованих змінних, додається ключ _route
,
який містить ім'я відповідного маршруту.
Якщо відповідний маршрут не знайдено, буде викликане ResourceNotFoundException.
Визначення маршрутів
Повне визначення маршруту може містити до семи частин:
- Маршрут шляху URL. Він співставляється з URL, який передано `RequestContext`,
і може містити названі рандомні заповнювачі (наприклад,
{placeholders}
), щоб відповідати динамічним частинам URL. - Масив значень за замовчуванням. Містить масив арбітражних значень, які будуть повернені, коли запит відповідає маршруту.
- Масив вимог. Він визначає обмеження значень заповнювачів у вигляді регулярних виразів.
- Масив опцій. Він містить внутрішні налаштування для маршруту та є найменш необхідним.
- Хостинг. Співставляється з хостингом запиту. Дивіться Як зробити так, щоб маршрут відповідав на засаді хоста, щоб дізнатися більше.
- Масив схем. Форсує певну HTTP-схему (
http
,https
). - Масив методів. Форсує певний метод HTTP-запиту (
HEAD
,GET
,POST
, ...).
Розгляньте наступний маршрут, який поєднує деякі з цих ідей:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
$route = new Route(
'/archive/{month}', // шлях
array('_controller' => 'showArchive'), // значення за замовчуванням values
array('month' => '[0-9]{4}-[0-9]{2}', 'subdomain' => 'www|m'), // вимоги
array(), // опції
'{subdomain}.example.com', // хостинг
array(), // схеми
array() // методи
);
// ...
$parameters = $matcher->match('/archive/2012-01');
// array(
// '_controller' => 'showArchive',
// 'month' => '2012-01',
// 'subdomain' => 'www',
// '_route' => ...
// )
$parameters = $matcher->match('/archive/foo');
// викликає ResourceNotFoundException
В цьому випадку, маршрут співставляється з /archive/2012-01
, так як метасимвол
{month}
відповідає регулярному виразу заданого метасимволу. Однак, /archive/foo
не відповідає, так як "foo" не підходить метасимволу місяця.
При використанні метасимволів, вони повертаються у вигляді масиву, при виклику match
.
Частина шляху, з якою співставляється метасимвол (наприклад, 2012-01
), використовується
в якость значення.
Tip
Якщо ви хочете співставити всі URL, які починаються з певного шляху і закінчуються довільним суфіксом, ви можете використовувати наступне визначення маршруту:
1 2 3 4 5
$route = new Route(
'/start/{suffix}',
array('suffix' => ''),
array('suffix' => '.*')
);
Використання префіксів
Ви можете додавати маршрути або інші екземпляри RouteCollection
до іншої колекції. Таким чином, ви можете побудувати дерево маршрутів. Крім того,
ви можете визначити префікс та значення за замовчуванням для параметрів, вимог, опцій,
схем та хостингу для всіх маршрутів піддерева, використовуючи методи, надані класом
RouteCollection
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
$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-запиту з цим класом через його конструктор:
1 2 3 4 5 6 7 8 9 10
public function __construct(
$baseUrl = '',
$method = 'GET',
$host = 'localhost',
$scheme = 'http',
$httpPort = 80,
$httpsPort = 443,
$path = '/',
$queryString = ''
)
Зазчиай ви можете передати значення зі змінної $_SERVER
, щоб наповнити
RequestContext. Але якщо ви використовуєте
компонент HttpFoundation , ви можете використати
його клас Request, щоб наповнити
RequestContext за допомогою скорочення:
1 2 3 4
use Symfony\Component\HttpFoundation\Request;
$context = new RequestContext();
$context->fromRequest(Request::createFromGlobals());
Генерування URL
В той час як UrlMatcher намагається знайти маршрут, який відповідає заданому запиту, ви можете також побудувати URL з певного маршруту:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
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
Note
Якщо ви визначили схему, генерується абсолютний URL, якщо схема поточного RequestContext не відповідає вимозі.
Перевірка існування шляху
У додатках, що динамічно розвиваються, може бути необхідним перевірити існування шляхе перед генеруванням URL. В таких випадках не використовуйте метод getRouteCollection() тому що він повторно створює кеш таблиці маршрутизації та уповільнює застосунок.
Замість цього спробуйте створити URL та ловіть виключення RouteNotFoundException, яке буде викликано, якщо маршрут не існує:
1 2 3 4 5 6 7 8 9
use Symfony\Component\Routing\Exception\RouteNotFoundException;
// ...
try {
$url = $generator->generate($dynamicRouteName, $parameters);
} catch (RouteNotFoundException $e) {
// маршрут не визначено...
}
Завантаження маршрутів з файлу
Ви вже бачили, як ви з легкістю можете додавати маршрути в колекцію прямо всередині PHP. Але ви також можете завантажувати маршрути із безлічі різних файлів.
Компонент Routing постачається з певною кількістю класів завантажувачів, і кожний надає вам можливість завантажувати колекцію визначення маршрутів із зовнішнього файлу якогось формату. Кожний завантажувач очікує екземпляр FileLocator, в якості аргументу конструктору. Ви можете використовувати FileLocator, щоб визначити масив шляхів, в яких завантажувач шукатиме запитувані файли. Якщо файл не знайдено, завантажувач повертає RouteCollection.
Якщо ви використовуєте YamlFileLoader
, то визначення маршруту виглядатиме так:
1 2 3 4 5 6 7 8
# routes.yaml
route1:
path: /foo
defaults: { _controller: 'MyController::fooAction' }
route2:
path: /foo/bar
defaults: { _controller: 'MyController::foobarAction' }
Щоб завантажити цей файл, ви можете використати наступний код. Передбачається,
що ваш файл routes.yaml
знаходиться в тому ж каталозі, що і в коді нижче:
1 2 3 4 5 6 7
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\YamlFileLoader;
// шукає всередині *цього* каталогу
$fileLocator = new FileLocator(array(__DIR__));
$loader = new YamlFileLoader($fileLocator);
$routes = $loader->load('routes.yaml');
Окрім YamlFileLoader, існує два інших завантажувача, які працюють таким же чином:
Якщо ви використовуєте PhpFileLoader, то вам необхідно надати ім'я PHP-файлу, який повертає RouteCollection:
1 2 3 4 5 6 7 8 9 10 11 12
// RouteProvider.php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
$routes = new RouteCollection();
$routes->add(
'route_name',
new Route('/foo', array('_controller' => 'ExampleController'))
);
// ...
return $routes;
Маршрути, як завершувачі
Також існує ClosureLoader, який викликає завершувач, та використовує результат в якості RouteCollection:
1 2 3 4 5 6 7 8
use Symfony\Component\Routing\Loader\ClosureLoader;
$closure = function () {
return new RouteCollection();
};
$loader = new ClosureLoader();
$routes = $loader->load($closure);
Маршрути, як анотації
Нарешті, існують AnnotationDirectoryLoader та AnnotationFileLoader, для завантаження визначень маршруту з анотацій класу. Конкретні деталі тут не розглядаються.
Note
Для того, щоб використовувати завантажувач анотацій, вам потрібно було встановити
у Composеr пакети doctrine/annotations
і doctrine/cache
.
Tip
Класи анотацій не завантажуються автоматично, так що вам потрібно завантажувати їх, використовуючи завантажувач класів таким чином:
1 2 3 4 5 6 7 8 9
use Composer\Autoload\ClassLoader;
use Doctrine\Common\Annotations\AnnotationRegistry;
/** @var ClassLoader $loader */
$loader = require __DIR__.'/../vendor/autoload.php';
AnnotationRegistry::registerLoader([$loader, 'loadClass']);
return $loader;
Маршрутизатор "все-в-одному"
Клас Router є пакетом "все-в-одному", для швидкого використання компоненту Routing. Конструктор очікує екземпляр завантажувача, шлях до головного визначення маршруту та деякі інші налаштування:
1 2 3 4 5 6 7
public function __construct(
LoaderInterface $loader,
$resource,
array $options = array(),
RequestContext $context = null,
LoggerInterface $logger = null
);
З опцією cache_dir
, ви можете увімкнути кешування маршруту (якщо ви надасте
шлях), або відключити кешування (якщо воно встановлене, як null
). Кешування
проводиться фоново автоматично, якщо ви хочете його використовувати. Базовим
прикладом класу Router буде:
1 2 3 4 5 6 7 8 9 10
$fileLocator = new FileLocator(array(__DIR__));
$requestContext = new RequestContext('/');
$router = new Router(
new YamlFileLoader($fileLocator),
'routes.yaml',
array('cache_dir' => __DIR__.'/cache'),
$requestContext
);
$router->match('/foo/bar');
Note
Якщо ви використовуєте кешування, компонент Routing скомпілює нові
класи, які зберігаються в cache_dir
. Це означає, що ваш скрипт повинен
мати дозвіл на запис в цій локації.
Підтримка маршрутизації Unicode
Компонент Routing підтримує символи UTF-8 у шляхах маршруту та вимогах. Завдяки
опції маршруту utf8
, ви можете зробити так, щоб Symfony співставляла та генерувала
маршрут з використанням UTF-8 символів:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Routing\Annotation\Route;
class DefaultController extends Controller
{
/**
* @Route("/category/{name}", name="route1", options={"utf8": true})
*/
public function category()
{
// ...
}
В цьому маршруті, опція utf8
встановлена як true
, що змушує Symfony
розглянути вимогу .
на відповідніть якимось символам UTF-8, замість одного
символу байту. Це означає, що наступні URL будуть відповідати: /category/日本語
,
/category/فارسی
, /category/한국어
, і т.д. У випадку, якщо ви хотіли знати,
ця опція також дозволяє вмикати та співставляти емоджі в URL.
Ви також можете включати UTF-8 рядки в якості вимог маршрутизації:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Routing\Annotation\Route;
class DefaultController extends Controller
{
/**
* @Route(
* "/category/{name}",
* name="route2",
* requirements={"default"="한국어"},
* options={"utf8": true}
* )
*/
public function default()
{
// ...
}
Tip
Окрім символів UTF-8, компонент Routing також підтримує всі
властивості PCRE Unicode, які екранують послідовності, що відповідають
загальним типам символів. Наприклад, \p{Lu}
відповідає будь-яким символам
верхнього регістру на будь-якій мові, \p{Greek}
відповідає будь-якому
грецькому символу, \P{Han}
відповідає будь-якому символу, який не включено
в скрипт Chinese Han.
Дізнайтеся більше
- Routing
- Как ограничить сопоставление маршрутов с помощью условий
- Як створити користувацький завантажувач маршрутів
- Як візуалізувати та налагоджувати маршрути
- Як підключати зовнішні джерела маршрутизації
- Как передать дополнительную информацию из маршрута в контроллер
- Як генерувати URL маршрутизації в JavaScript
- Як зробити так, щоб маршрут відповідав на засаді хоста
- Як визначати необовʼязкові заповнювачі
- Як сконфігурувати перенаправлення без користувацького контролера
- Перенаправлення URL із замикаючим слешем
- Як визначати вимоги маршруту
- Пошук маршрутів з бази даних: Symfony CMF DynamicRouter
- Як змусити маршрути завжди використовувати HTTPS або HTTP
- Как использовать параметры сервис-контейнера в ваших маршрутах
- Як дозволити символ "/" у параметрі маршруту
- Контролер
- Розширення розвʼязування аргументу дії
- Як налаштувати сторінки помилок
- Як пересилати запити іншому контролеру
- Як визначати контролери як сервіси
- Як створити вед-сервіс SOAP у контролері Symfony
- Як завантажувати файли
- Розширення розвʼязування аргументу дії