Skip to content

Commit ac15bf5

Browse files
committed
[#3022] Adding framework documentation for routing expressions
1 parent 93e8cd2 commit ac15bf5

File tree

1 file changed

+94
-4
lines changed

1 file changed

+94
-4
lines changed

book/routing.rst

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -507,10 +507,11 @@ to the ``{page}`` parameter.
507507
| /blog/my-blog-post | blog | {page} = my-blog-post |
508508
+--------------------+-------+-----------------------+
509509

510-
The answer to the problem is to add route *requirements*. The routes in this
511-
example would work perfectly if the ``/blog/{page}`` path *only* matched
512-
URLs where the ``{page}`` portion is an integer. Fortunately, regular expression
513-
requirements can easily be added for each parameter. For example:
510+
The answer to the problem is to add route *requirements* or route *conditions*
511+
(see :ref:`book-routing-conditions`). The routes in this example would work
512+
perfectly if the ``/blog/{page}`` path *only* matched URLs where the ``{page}``
513+
portion is an integer. Fortunately, regular expression requirements can easily
514+
be added for each parameter. For example:
514515

515516
.. configuration-block::
516517

@@ -717,6 +718,95 @@ You can also match on the HTTP *host* of the incoming request. For more
717718
information, see :doc:`/components/routing/hostname_pattern` in the Routing
718719
component documentation.
719720

721+
.. _book-routing-conditions:
722+
723+
Completely Customized Route Matching with Conditions
724+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
725+
726+
.. versionadded:: 2.4
727+
Route conditions were introduced in Symfony 2.4.
728+
729+
As you've seen, a route can be made to match only certain routing wildcards
730+
(via regular expressions), HTTP methods, or host names. But the routing system
731+
can be extended to almost an infinite flexibility with ``conditions``:
732+
733+
.. configuration-block::
734+
735+
.. code-block:: yaml
736+
737+
contact:
738+
path: /contact
739+
defaults: { _controller: AcmeDemoBundle:Main:contact }
740+
condition: "context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'"
741+
742+
.. code-block:: xml
743+
744+
<?xml version="1.0" encoding="UTF-8" ?>
745+
<routes xmlns="http://symfony.com/schema/routing"
746+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
747+
xsi:schemaLocation="http://symfony.com/schema/routing
748+
http://symfony.com/schema/routing/routing-1.0.xsd">
749+
750+
<route id="contact"
751+
path="/contact"
752+
condition="context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'"
753+
>
754+
<default key="_controller">AcmeDemoBundle:Main:contact</default>
755+
</route>
756+
</routes>
757+
758+
.. code-block:: php
759+
760+
use Symfony\Component\Routing\RouteCollection;
761+
use Symfony\Component\Routing\Route;
762+
763+
$collection = new RouteCollection();
764+
$collection->add('contact', new Route(
765+
'/contact', array(
766+
'_controller' => 'AcmeDemoBundle:Main:contact',
767+
),
768+
array(),
769+
array(),
770+
'',
771+
array(),
772+
array(),
773+
'context.getMethod() in ["GET", "HEAD"] and request.headers.get("User-Agent") matches "/firefox/i"'
774+
));
775+
776+
return $collection;
777+
778+
The ``condition`` is an expression, and you can learn more about it syntax
779+
here: :doc:`/components/expression_language/syntax`. With this, the route
780+
won't match unless the HTTP method is either GET or HEAD *and* if the ``User-Agent``
781+
header matches ``firefox``.
782+
783+
You can do any complex logic you need here by leveraging two variables that
784+
are passed into the expression:
785+
786+
* ``context``: An instance of :class:`Symfony\\Component\\Routing\\RequestContext`,
787+
which holds the most fundamental information about the route being matched;
788+
* ``request``: The Symfony :class:`Symfony\\Component\\HttpFoundation\\Request``
789+
object (see :ref:`component-http-foundation-request`).
790+
791+
.. caution::
792+
793+
Conditions are *not* taken into account when generating a URL.
794+
795+
.. sidebar:: Expressions are Compiled to PHP
796+
797+
Behind the scenes, expressions are compiled down to raw PHP. Our example
798+
would generate the following PHP in the cache directory::
799+
800+
if (rtrim($pathinfo, '/contact') === '' && (
801+
in_array($context->getMethod(), array(0 => "GET", 1 => "HEAD"))
802+
&& preg_match("/firefox/i", $request->headers->get("User-Agent"))
803+
)) {
804+
// ...
805+
}
806+
807+
Because of this, using the ``condition`` key causes no extra roverhead
808+
beyond the time it takes for the underlying PHP to execute.
809+
720810
.. index::
721811
single: Routing; Advanced example
722812
single: Routing; _format parameter

0 commit comments

Comments
 (0)