Skip to content

Commit ee357bf

Browse files
committed
feature #4790 [Cookbook][Routing] Update custom_route_loader.rst (xelaris)
This PR was merged into the 2.3 branch. Discussion ---------- [Cookbook][Routing] Update custom_route_loader.rst | Q | A | ------------- | --- | Doc fix? | yes | New docs? | no | Applies to | 2.3+ | Fixed tickets | Just some tweaks (including "Acme\DemoBundle" => "AppBundle"). While reading this chapter I wonder, if > A custom route loader allows you to add routes to an application without including them, for example, in a YAML file. [...] This may be especially important when you want to make the bundle reusable, or when you have open-sourced it as this would slow down the installation process and make it error-prone. may raise false expectations. Since also with a route loader it is still required to add something to the routing.yml (or xml). I don't see the benefit of using a custom route loader in a reusable bundle over importing a YAML file from a third-party bundle like FOSUserBundle. It makes totally sense for something like the FOSRestBundle does (generating routes based on conventions), but the chapter introduction sounds, like a Bundle could load its routes without manual tweaks to the config. If I am not wrong, this isn't possible, isn't it? Commits ------- 08b1527 Add filename comments to code blocks fe1a574 Change code example to extend from Loader class bd6e3f3 Rewrite first paragraph 46d10a2 [Cookbook][Routing] Update custom_route_loader.rst
2 parents 931faaa + 08b1527 commit ee357bf

File tree

1 file changed

+69
-56
lines changed

1 file changed

+69
-56
lines changed

cookbook/routing/custom_route_loader.rst

Lines changed: 69 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,28 @@
44
How to Create a custom Route Loader
55
===================================
66

7-
A custom route loader allows you to add routes to an application without
8-
including them, for example, in a YAML file. This comes in handy when
9-
you have a bundle but don't want to manually add the routes for the bundle
10-
to ``app/config/routing.yml``. This may be especially important when you want
11-
to make the bundle reusable, or when you have open-sourced it as this would
12-
slow down the installation process and make it error-prone.
13-
14-
Alternatively, you could also use a custom route loader when you want your
15-
routes to be automatically generated or located based on some convention or
16-
pattern. One example is the `FOSRestBundle`_ where routing is generated based
17-
off the names of the action methods in a controller.
7+
What is a Custom Route Loader
8+
-----------------------------
9+
10+
A custom route loader enables you to generate routes based on some
11+
conventions or patterns. A great example for this use-case is the
12+
`FOSRestBundle`_ where routes are generated based on the names of the
13+
action methods in a controller.
14+
15+
A custom route loader does not enable your bundle to inject routes
16+
without the need to modify the routing configuration
17+
(e.g. ``app/config/routing.yml``) manually.
18+
If your bundle provides routes, whether via a configuration file, like
19+
the `WebProfilerBundle` does, or via a custom route loader, like the
20+
`FOSRestBundle`_ does, an entry in the routing configuration is always
21+
necessary.
1822

1923
.. note::
2024

2125
There are many bundles out there that use their own route loaders to
2226
accomplish cases like those described above, for instance
23-
`FOSRestBundle`_, `JMSI18nRoutingBundle`_, `KnpRadBundle`_ and `SonataAdminBundle`_.
27+
`FOSRestBundle`_, `JMSI18nRoutingBundle`_, `KnpRadBundle`_ and
28+
`SonataAdminBundle`_.
2429

2530
Loading Routes
2631
--------------
@@ -35,20 +40,18 @@ and therefore have two important methods:
3540
:method:`Symfony\\Component\\Config\\Loader\\LoaderInterface::supports`
3641
and :method:`Symfony\\Component\\Config\\Loader\\LoaderInterface::load`.
3742

38-
Take these lines from the ``routing.yml`` in the AcmeDemoBundle of the Standard
39-
Edition:
43+
Take these lines from the ``routing.yml`` in the Symfony Standard Edition:
4044

4145
.. code-block:: yaml
4246
43-
# src/Acme/DemoBundle/Resources/config/routing.yml
44-
_demo:
45-
resource: "@AcmeDemoBundle/Controller/DemoController.php"
47+
# app/config/routing.yml
48+
app:
49+
resource: @AppBundle/Controller/
4650
type: annotation
47-
prefix: /demo
4851
49-
When the main loader parses this, it tries all the delegate loaders and calls
52+
When the main loader parses this, it tries all registered delegate loaders and calls
5053
their :method:`Symfony\\Component\\Config\\Loader\\LoaderInterface::supports`
51-
method with the given resource (``@AcmeDemoBundle/Controller/DemoController.php``)
54+
method with the given resource (``@AppBundle/Controller/``)
5255
and type (``annotation``) as arguments. When one of the loader returns ``true``,
5356
its :method:`Symfony\\Component\\Config\\Loader\\LoaderInterface::load` method
5457
will be called, which should return a :class:`Symfony\\Component\\Routing\\RouteCollection`
@@ -59,20 +62,24 @@ Creating a custom Loader
5962

6063
To load routes from some custom source (i.e. from something other than annotations,
6164
YAML or XML files), you need to create a custom route loader. This loader
62-
should implement :class:`Symfony\\Component\\Config\\Loader\\LoaderInterface`.
65+
has to implement :class:`Symfony\\Component\\Config\\Loader\\LoaderInterface`.
66+
67+
In most cases it's better not to implement
68+
:class:`Symfony\\Component\\Config\\Loader\\LoaderInterface`
69+
yourself, but extend from :class:`Symfony\\Component\\Config\\Loader\\Loader`.
6370

6471
The sample loader below supports loading routing resources with a type of
6572
``extra``. The type ``extra`` isn't important - you can just invent any resource
6673
type you want. The resource name itself is not actually used in the example::
6774

68-
namespace Acme\DemoBundle\Routing;
75+
// src/AppBundle/Routing/ExtraLoader.php
76+
namespace AppBundle\Routing;
6977

70-
use Symfony\Component\Config\Loader\LoaderInterface;
71-
use Symfony\Component\Config\Loader\LoaderResolverInterface;
78+
use Symfony\Component\Config\Loader\Loader;
7279
use Symfony\Component\Routing\Route;
7380
use Symfony\Component\Routing\RouteCollection;
7481

75-
class ExtraLoader implements LoaderInterface
82+
class ExtraLoader extends Loader
7683
{
7784
private $loaded = false;
7885

@@ -87,14 +94,14 @@ type you want. The resource name itself is not actually used in the example::
8794
// prepare a new route
8895
$path = '/extra/{parameter}';
8996
$defaults = array(
90-
'_controller' => 'AcmeDemoBundle:Demo:extra',
97+
'_controller' => 'AppBundle:Extra:extra',
9198
);
9299
$requirements = array(
93100
'parameter' => '\d+',
94101
);
95102
$route = new Route($path, $defaults, $requirements);
96103

97-
// add the new route to the route collection:
104+
// add the new route to the route collection
98105
$routeName = 'extraRoute';
99106
$routes->add($routeName, $route);
100107

@@ -107,32 +114,36 @@ type you want. The resource name itself is not actually used in the example::
107114
{
108115
return 'extra' === $type;
109116
}
117+
}
110118

111-
public function getResolver()
112-
{
113-
// needed, but can be blank, unless you want to load other resources
114-
// and if you do, using the Loader base class is easier (see below)
115-
}
119+
Make sure the controller you specify really exists. In this case you
120+
have to create an ``extraAction`` method in the ``ExtraController``
121+
of the ``AppBundle``::
122+
123+
// src/AppBundle/Controller/ExtraController.php
124+
namespace AppBundle\Controller;
116125

117-
public function setResolver(LoaderResolverInterface $resolver)
126+
use Symfony\Component\HttpFoundation\Response;
127+
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
128+
129+
class ExtraController extends Controller
130+
{
131+
public function extraAction($parameter)
118132
{
119-
// same as above
133+
return new Response($parameter);
120134
}
121135
}
122136

123-
.. note::
124-
125-
Make sure the controller you specify really exists.
126-
127137
Now define a service for the ``ExtraLoader``:
128138

129139
.. configuration-block::
130140

131141
.. code-block:: yaml
132142
143+
# app/config/services.yml
133144
services:
134-
acme_demo.routing_loader:
135-
class: Acme\DemoBundle\Routing\ExtraLoader
145+
app.routing_loader:
146+
class: AppBundle\Routing\ExtraLoader
136147
tags:
137148
- { name: routing.loader }
138149
@@ -144,7 +155,7 @@ Now define a service for the ``ExtraLoader``:
144155
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
145156
146157
<services>
147-
<service id="acme_demo.routing_loader" class="Acme\DemoBundle\Routing\ExtraLoader">
158+
<service id="app.routing_loader" class="AppBundle\Routing\ExtraLoader">
148159
<tag name="routing.loader" />
149160
</service>
150161
</services>
@@ -156,14 +167,15 @@ Now define a service for the ``ExtraLoader``:
156167
157168
$container
158169
->setDefinition(
159-
'acme_demo.routing_loader',
160-
new Definition('Acme\DemoBundle\Routing\ExtraLoader')
170+
'app.routing_loader',
171+
new Definition('AppBundle\Routing\ExtraLoader')
161172
)
162173
->addTag('routing.loader')
163174
;
164175
165-
Notice the tag ``routing.loader``. All services with this tag will be marked
166-
as potential route loaders and added as specialized routers to the
176+
Notice the tag ``routing.loader``. All services with this *tag* will be marked
177+
as potential route loaders and added as specialized route loaders to the
178+
``routing.loader`` *service*, which is an instance of
167179
:class:`Symfony\\Bundle\\FrameworkBundle\\Routing\\DelegatingLoader`.
168180

169181
Using the custom Loader
@@ -177,7 +189,7 @@ Instead, you only need to add a few extra lines to the routing configuration:
177189
.. code-block:: yaml
178190
179191
# app/config/routing.yml
180-
AcmeDemoBundle_Extra:
192+
app_extra:
181193
resource: .
182194
type: extra
183195
@@ -201,8 +213,8 @@ Instead, you only need to add a few extra lines to the routing configuration:
201213
202214
return $collection;
203215
204-
The important part here is the ``type`` key. Its value should be "extra".
205-
This is the type which the ``ExtraLoader`` supports and this will make sure
216+
The important part here is the ``type`` key. Its value should be "extra" as
217+
this is the type which the ``ExtraLoader`` supports and this will make sure
206218
its ``load()`` method gets called. The ``resource`` key is insignificant
207219
for the ``ExtraLoader``, so it is set to ".".
208220

@@ -215,11 +227,11 @@ for the ``ExtraLoader``, so it is set to ".".
215227
More advanced Loaders
216228
---------------------
217229

218-
In most cases it's better not to implement
219-
:class:`Symfony\\Component\\Config\\Loader\\LoaderInterface`
220-
yourself, but extend from :class:`Symfony\\Component\\Config\\Loader\\Loader`.
221-
This class knows how to use a :class:`Symfony\\Component\\Config\\Loader\\LoaderResolver`
222-
to load secondary routing resources.
230+
If your custom route loader extends from
231+
:class:`Symfony\\Component\\Config\\Loader\\Loader` as shown above, you
232+
can also make use of the provided resolver, an instance of
233+
:class:`Symfony\\Component\\Config\\Loader\\LoaderResolver`, to load secondary
234+
routing resources.
223235

224236
Of course you still need to implement
225237
:method:`Symfony\\Component\\Config\\Loader\\LoaderInterface::supports`
@@ -228,7 +240,8 @@ Whenever you want to load another resource - for instance a YAML routing
228240
configuration file - you can call the
229241
:method:`Symfony\\Component\\Config\\Loader\\Loader::import` method::
230242

231-
namespace Acme\DemoBundle\Routing;
243+
// src/AppBundle/Routing/AdvancedLoader.php
244+
namespace AppBundle\Routing;
232245

233246
use Symfony\Component\Config\Loader\Loader;
234247
use Symfony\Component\Routing\RouteCollection;
@@ -239,7 +252,7 @@ configuration file - you can call the
239252
{
240253
$collection = new RouteCollection();
241254

242-
$resource = '@AcmeDemoBundle/Resources/config/import_routing.yml';
255+
$resource = '@AppBundle/Resources/config/import_routing.yml';
243256
$type = 'yaml';
244257

245258
$importedRoutes = $this->import($resource, $type);
@@ -251,7 +264,7 @@ configuration file - you can call the
251264

252265
public function supports($resource, $type = null)
253266
{
254-
return $type === 'advanced_extra';
267+
return 'advanced_extra' === $type;
255268
}
256269
}
257270

0 commit comments

Comments
 (0)