Как ограничить сопоставление маршрутов с помощью условий

Маршрут может быть создан так, чтобы совпадать только с определенными маршрутными заполнителями (с помощью обычных выражений), HTTP-методами, или именами хостов. Если вам нужно больше гибкости в определении логики произвольного совпадения, используйте опцию маршрутизации conditions:

  • YAML
    1
    2
    3
    4
    5
    # config/routes.yaml
    contact:
        path:       /contact
        controller: 'App\Controller\DefaultController::contact'
        condition:  "context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'"
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    <!-- config/routes.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing
            http://symfony.com/schema/routing/routing-1.0.xsd">
    
        <route id="contact" path="/contact">
            <default key="_controller">App\Controller\DefaultController::contact</default>
            <condition>context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'</condition>
        </route>
    </routes>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // config/routes.php
    use Symfony\Component\Routing\RouteCollection;
    use Symfony\Component\Routing\Route;
    
    $collection = new RouteCollection();
    $collection->add('contact', new Route(
        '/contact', array(
            '_controller' => 'App\Controller\DefaultController::contact',
        ),
        array(),
        array(),
        '',
        array(),
        array(),
        'context.getMethod() in ["GET", "HEAD"] and request.headers.get("User-Agent") matches "/firefox/i"'
    ));
    
    return $collection;
    

Сondition - это выражение, и вы можете узнать больше о его синтаксисе здесь The Expression Syntax. С ним маршрут не будет совпадать, кроме случаев, когда HTTP-метод является GET или HEAD и если заголовок User-Agent соответствует firefox.

Вы можете создавать в выражении логику такой сложности, как вам нужно, используя две переменные, которые передаются в выражение:

context
Экземпляр класса RequestContext, который содержит самую фундаментальную информацию о соответствующем маршруте.
request
Объект Symfony Request (см. Request).

Caution

Условия не берутся в расчёт при генерировании URL.

Ха кулисами, выражения компилираются в сырой PHP. Наш пример сгенерирует следующий PHP в каталоге кеша:

1
2
3
4
5
6
if (rtrim($pathinfo, '/contact') === '' && (
    in_array($context->getMethod(), array(0 => "GET", 1 => "HEAD"))
    && preg_match("/firefox/i", $request->headers->get("User-Agent"))
)) {
    // ...
}

Благодаря этому, использование ключа condition не создаёт дополнительных издержек, кроме времени, которое требуется для выполнения базового PHP.

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.