8000 minor #11113 Improved routing section (Jules Pietri) · symfony/symfony-docs@735ef0a · GitHub
[go: up one dir, main page]

Skip to content

Commit 735ef0a

Browse files
committed
minor #11113 Improved routing section (Jules Pietri)
This PR was merged into the 3.4 branch. Discussion ---------- Improved routing section A back port of some 4.2 tweaks. I'll open another one against 4.2 after this one is merged. Also we should get rid of some conflicts in the future after this one. Commits ------- 0f1f2ea Improved routing section
2 parents fd8e772 + 0f1f2ea commit 735ef0a

13 files changed

+178
-91
lines changed

components/routing.rst

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ your autoloader to load the Routing component::
3939

4040
use Symfony\Component\Routing\Matcher\UrlMatcher;
4141
use Symfony\Component\Routing\RequestContext;
42-
use Symfony\Component\Routing\RouteCollection;
4342
use Symfony\Component\Routing\Route;
43+
use Symfony\Component\Routing\RouteCollection;
4444

4545
$route = new Route('/foo', ['_controller' => 'MyController']);
4646
$routes = new RouteCollection();
@@ -82,20 +82,24 @@ be thrown.
8282
Defining Routes
8383
~~~~~~~~~~~~~~~
8484

85-
A full route definition can contain up to seven parts:
85+
A full route definition can contain up to eight parts:
8686

87-
#. The URL path route. This is matched against the URL passed to the `RequestContext`,
88-
and can contain named wildcard placeholders (e.g. ``{placeholders}``)
89-
to match dynamic parts in the URL.
87+
#. The URL pattern. This is matched against the URL passed to the
88+
``RequestContext``. It is not a regular expression, but can contain named
89+
wildcard placeholders (e.g. ``{slug}``) to match dynamic parts in the URL.
90+
The component will create the regular expression from it.
9091

91-
#. An array of default values. This contains an array of arbitrary values
92-
that will be returned when the request matches the route.
92+
#. An array of default parameters. This contains an array of arbitrary values
93+
that will be returned when the request matches the route. It is used by
94+
convention to map a controller to the route.
9395

9496
#. An array of requirements. These define constraints for the values of the
95-
placeholders as regular expressions.
97+
placeholders in the pattern as regular expressions.
9698

97-
#. An array of options. These contain internal settings for the route and
98-
are the least commonly needed.
99+
#. An array of options. These contain advanced settings for the route and
100+
can be used to control encoding or customize compilation.
101+
See :ref:`routing-unicode-support` below. You can learn more about them by
102+
reading :method:`Symfony\\Component\\Routing\\Route::setOptions` implementation.
99103

100104
#. A host. This is matched against the host of the request. See
101105
:doc:`/routing/hostname_pattern` for more details.
@@ -105,6 +109,10 @@ A full route definition can contain up to seven parts:
105109
#. An array of methods. These enforce a certain HTTP request method (``HEAD``,
106110
``GET``, ``POST``, ...).
107111

112+
#. A condition, using the :doc:`/components/expression_language/syntax`.
113+
A string that must evaluate to ``true`` so the route matches. See
114+
:doc:`/routing/conditions` for more details.
115+
108116
Take the following route, which combines several of these ideas::
109117

110118
$route = new Route(
@@ -114,7 +122,8 @@ Take the following route, which combines several of these ideas::
114122
[], // options
115123
'{subdomain}.example.com', // host
116124
[], // schemes
117-
[] // methods
125+
[], // methods
126+
'context.getHost() matches "/(secure|admin).example.com/"' // condition
118127
);
119128

120129
// ...
@@ -138,19 +147,22 @@ When using wildcards, these are returned in the array result when calling
138147
``match``. The part of the path that the wildcard matched (e.g. ``2012-01``) is used
139148
as value.
140149

141-
.. tip::
150+
A placeholder matches any character except slashes ``/`` by default, unless you define
151+
a specific requirement for it.
152+
The reason is that they are used by convention to separate different placeholders.
142153

143-
If you want to match all URLs which start with a certain path and end in an
144-
arbitrary suffix you can use the following route definition::
154+
If you want a placeholder to match anything, it must be the last of the route::
145155

146-
$route = new Route(
147-
'/start/{suffix}',
148-
['suffix' => ''],
149-
['suffix' => '.*']
150-
);
156+
$route = new Route(
157+
'/start/{required}/{anything}',
158+
['required' => 'default'], // should always be defined
159+
['anything' => '.*'] // explicit requirement to allow "/"
160+
);
151161

152-
Using Prefixes
153-
~~~~~~~~~~~~~~
162+
Learn more about it by reading :ref:`routing/slash_in_parameter`.
163+
164+
Using Prefixes and Collection Settings
165+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
154166

155167
You can add routes or other instances of
156168
:class:`Symfony\\Component\\Routing\\RouteCollection` to *another* collection.
@@ -166,11 +178,12 @@ host to all routes of a subtree using methods provided by the
166178
$subCollection->add(...);
167179
$subCollection->addPrefix('/prefix');
168180
$subCollection->addDefaults([...]);
169-
$subCollection->addRequirements([]);
170-
$subCollection->addOptions([]);
171-
$subCollection->setHost('admin.example.com');
181+
$subCollection->addRequirements([...]);
182+
$subCollection->addOptions([...]);
183+
$subCollection->setHost('{subdomain}.example.com');
172184
$subCollection->setMethods(['POST']);
173185
$subCollection->setSchemes(['https']);
186+
$subCollection->setCondition('context.getHost() matches "/(secure|admin).example.com/"');
174187

175188
$rootCollection->addCollection($subCollection);
176189

@@ -210,7 +223,7 @@ Generate a URL
210223

211224
While the :class:`Symfony\\Component\\Routing\\Matcher\\UrlMatcher` tries
212225
to find a route that fits the given request you can also build a URL from
213-
a certain route::
226+
a certain route with the :class:`Symfony\\Component\\Routing\\Generator\\UrlGenerator`::
214227

215228
use Symfony\Component\Routing\Generator\UrlGenerator;
216229
use Symfony\Component\Routing\RequestContext;
@@ -260,7 +273,7 @@ when the route doesn't exist::
260273
Load Routes from a File
261274
~~~~~~~~~~~~~~~~~~~~~~~
262275

263-
You've already seen how you can easily add routes to a collection right inside
276+
You've already seen how you can add routes to a collection right inside
264277
PHP. But you can also load routes from a number of different files.
265278

266279
The Routing component comes with a number of loader classes, each giving
@@ -347,7 +360,7 @@ The all-in-one Router
347360
~~~~~~~~~~~~~~~~~~~~~
348361

349362
The :class:`Symfony\\Component\\Routing\\Router` class is an all-in-one package
350-
to quickly use the Routing component. The constructor expects a loader instance,
363+
to use the Routing component. The constructor expects a loader instance,
351364
a path to the main route definition and some other settings::
352365

353366
public function __construct(
@@ -372,14 +385,17 @@ automatically in the background if you want to use it. A basic example of the
372385
['cache_dir' => __DIR__.'/cache'],
373386
$requestContext
374387
);
375-
$router->match('/foo/bar');
388+
$parameters = $router->match('/foo/bar');
389+
$url = $router->generate('some_route', ['parameter' => 'value']);
376390

377391
.. note::
378392

379393
If you use caching, the Routing component will compile new classes which
380394
are saved in the ``cache_dir``. This means your script must have write
381395
permissions for that location.
382396

397+
.. _routing-unicode-support:
398+
383399
Unicode Routing Support
384400
~~~~~~~~~~~~~~~~~~~~~~~
385401

@@ -481,7 +497,7 @@ You can also include UTF-8 strings as routing requirements:
481497
* @Route(
482498
* "/category/{name}",
483499
* name="route2",
484-
* requirements={"default"="한국어"},
500+
* defaults={"name": "한국어"},
485501
* options={"utf8": true}
486502
* )
487503
*/
@@ -494,10 +510,10 @@ You can also include UTF-8 strings as routing requirements:
494510
495511
# app/config/routing.yml
496512
route2:
497-
path: /default/{default}
498-
defaults: { _controller: 'AppBundle:Default:default' }
499-
requirements:
500-
default: "한국어"
513+
path: /category/{name}
514+
defaults:
515+
_controller: 'AppBundle:Default:default'
516+
name: '한국어'
501517
options:
502518
utf8: true
503519
@@ -510,9 +526,9 @@ You can also include UTF-8 strings as routing requirements:
510526
xsi:schemaLocation="http://symfony.com/schema/routing
511527
https://symfony.com/schema/routing/routing-1.0.xsd">
512528
513-
<route id="route2" path="/default/{default}">
529+
<route id="route2" path="/category/{name}">
514530
<default key="_controller">AppBundle:Default:default</default>
515-
<requirement key="default">한국어</requirement>
531+
<default key="name">한국어</requirement>
516532
<option key="utf8">true</option>
517533
</route>
518534
</routes>
@@ -527,10 +543,9 @@ You can also include UTF-8 strings as routing requirements:
527543
$routes->add('route2', new Route('/default/{default}',
528544
[
529545
'_controller' => 'AppBundle:Default:default',
546+
'name' => '한국어',
530547
],
531-
[
532-
'default' => '한국어',
533-
],
548+
[],
534549
[
535550
'utf8' => true,
536551
]

routing.rst

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
Routing
55
=======
66

7-
Beautiful URLs are an absolute must for any serious web application. This
8-
means leaving behind ugly URLs like ``index.php?article_id=57`` in favor
9-
of something like ``/read/intro-to-symfony``.
7+
Beautiful URLs are a must for any serious web application. This means leaving
8+
behind ugly URLs like ``index.php?article_id=57`` in favor of something like
9+
``/read/intro-to-symfony``.
1010

1111
Having flexibility is even more important. What if you need to change the
12-
URL of a page from ``/blog`` to ``/news``? How many links should you need to
12+
URL of a page from ``/blog`` to ``/news``? How many links would you need to
1313
hunt down and update to make the change? If you're using Symfony's router,
14-
the change is simple.
14+
the change should be trivial.
1515

1616
The Symfony router lets you define creative URLs that you map to different
1717
areas of your application. By the end of this article, you'll be able to:
@@ -27,10 +27,13 @@ areas of your application. By the end of this article, you'll be able to:
2727
Routing Examples
2828
----------------
2929

30-
A *route* is a map from a URL path to a controller. For example, suppose
31-
you want to match any URL like ``/blog/my-post`` or ``/blog/all-about-symfony``
32-
and send it to a controller that can look up and render that blog post.
33-
The route is simple:
30+
A *route* is a map from a URL path to attributes (i.e a controller). Suppose
31+
you want one route that matches ``/blog`` exactly and another more dynamic
32+
route that can match *any* URL like ``/blog/my-post`` or
33+
``/blog/all-about-symfony``.
34+
35+
Routes can be configured in YAML, XML, PHP or annotations. All formats provide
36+
the same features and performance, so choose the one you prefer:
3437

3538
.. configuration-block::
3639

@@ -56,6 +59,7 @@ The route is simple:
5659
5760
/**
5861
* Matches /blog/*
62+
* but not /blog/slug/extra-part
5963
*
6064
* @Route("/blog/{slug}", name="blog_show")
6165
*/
@@ -72,10 +76,13 @@ The route is simple:
7276
7377
# app/config/routing.yml
7478
blog_list:
79+
# Matches /blog exactly
7580
path: /blog
7681
defaults: { _controller: AppBundle:Blog:list }
7782
7883
blog_show:
84+
# Matches /blog/*
85+
# but not /blog/slug/extra-part
7986
path: /blog/{slug}
8087
defaults: { _controller: AppBundle:Blog:show }
8188
@@ -88,10 +95,13 @@ The route is simple:
8895
xsi:schemaLocation="http://symfony.com/schema/routing
8996
https://symfony.com/schema/routing/routing-1.0.xsd">
9097
98+
<!-- Matches /blog exactly -->
9199
<route id="blog_list" path="/blog">
92100
<default key="_controller">AppBundle:Blog:list</default>
93101
</route>
94102
103+
<!-- Matches /blog/* -->
104+
<!-- but not /blog/slug/extra-part -->
95105
<route id="blog_show" path="/blog/{slug}">
96106
<default key="_controller">AppBundle:Blog:show</default>
97107
</route>
@@ -104,9 +114,12 @@ The route is simple:
104114
use Symfony\Component\Routing\Route;
105115
106116
$routes = new RouteCollection();
117+
// Matches /blog exactly
107118
$routes->add('blog_list', new Route('/blog', [
108119
'_controller' => 'AppBundle:Blog:list',
109120
]));
121+
// Matches /blog/*
122+
// but not /blog/slug/extra-part
110123
$routes->add('blog_show', new Route('/blog/{slug}', [
111124
'_controller' => 'AppBundle:Blog:show',
112125
]));
@@ -119,13 +132,21 @@ Thanks to these two routes:
119132
is executed;
120133

121134
* If the user goes to ``/blog/*``, the second route is matched and ``showAction()``
122-
is executed. Because the route path is ``/blog/{slug}``, a ``$slug`` variable is
123-
passed to ``showAction()`` matching that value. For example, if the user goes to
135+
is executed. Because the route path is ``/blog/{slug}``, a ``$slug`` variable
136+
is passed to ``showAction()`` matching that value. For example, if the user goes to
124137
``/blog/yay-routing``, then ``$slug`` will equal ``yay-routing``.
125138

126-
Whenever you have a ``{placeholder}`` in your route path, that portion becomes a
127-
wildcard: it matches *any* value. Your controller can now *also* have an argument
128-
called ``$placeholder`` (the wildcard and argument names *must* match).
139+
Whenever you have a ``{placeholder}`` in your route path, that portion becomes
140+
a wildcard: it matches *any* value. Your controller can now *also* have an
141+
argument called ``$placeholder`` (the wildcard and argument names *must*
142+
match).
143+
144+
.. caution::
145+
146+
However the slash ``/`` is ignored by default in placeholder values because
147+
the router uses it as separator between different placeholders.
148+
To learn more about this, you can read
149+
:ref:`routing/slash_in_parameter`.
129150

130151
Each route also has an internal name: ``blog_list`` and ``blog_show``. These can
131152
be anything (as long as each is unique) and don't have any meaning yet.

routing/conditions.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ How to Restrict Route Matching through Conditions
66

77
A route can be made to match only certain routing placeholders (via regular
88
expressions), HTTP methods, or host names. If you need more flexibility to
9-
define arbitrary matching logic, use the ``conditions`` routing option:
9+
define arbitrary matching logic, use the ``condition`` routing setting:
1010

1111
.. configuration-block::
1212

routing/custom_route_loader.rst

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,17 @@ and configure the service and method to call:
102102
103103
return $routes;
104104
105-
In this example, the routes are loaded by calling the ``loadRoutes()`` method of
106-
the service whose ID is ``admin_route_loader``. Your service doesn't have to
105+
In this example, the routes are loaded by calling the ``loadRoutes()`` method
106+
of the service whose ID is ``admin_route_loader``. Your service doesn't have to
107107
extend or implement any special class, but the called method must return a
108108
:class:`Symfony\\Component\\Routing\\RouteCollection` object.
109109

110+
.. note::
111+
112+
The routes defined using service route loaders will be automatically
113+
cached by the framework. So whenever your service should load new routes,
114+
don't forget to clear the cache.
115+
110116
Creating a custom Loader
111117
------------------------
112118

@@ -219,8 +225,7 @@ Now define a service for the ``ExtraLoader``:
219225
220226
use AppBundle\Routing\ExtraLoader;
221227
222-
$container
223-
->autowire(ExtraLoader::class)
228+
$container->autowire(ExtraLoader::class)
224229
->addTag('routing.loader')
225230
;
226231
@@ -229,7 +234,7 @@ as potential route loaders and added as specialized route loaders to the
229234
``routing.loader`` *service*, which is an instance of
230235
:class:`Symfony\\Bundle\\FrameworkBundle\\Routing\\DelegatingLoader`.
231236

232-
Using the custom Loader
237+
Using the Custom Loader
233238
~~~~~~~~~~~~~~~~~~~~~~~
234239

235240
If you did nothing else, your custom routing loader would *not* be called.
@@ -276,7 +281,7 @@ for the ``ExtraLoader``, so it is set to ".".
276281
cached by the framework. So whenever you change something in the loader
277282
class itself, don't forget to clear the cache.
278283

279-
More advanced Loaders
284+
More Advanced Loaders
280285
---------------------
281286

282287
If your custom route loader extends from

0 commit comments

Comments
 (0)
0