Skip to content
This repository was archived by the owner on Sep 16, 2021. It is now read-only.

Commit 6592c97

Browse files
committed
Rewrote introduction
1 parent d8e1220 commit 6592c97

File tree

1 file changed

+198
-94
lines changed

1 file changed

+198
-94
lines changed

bundles/routing_auto/introduction.rst

Lines changed: 198 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -5,72 +5,72 @@
55
RoutingAutoBundle
66
=================
77

8-
.. include:: _outdate-caution.rst.inc
9-
108
.. include:: _not-stable-caution.rst.inc
119

12-
The RoutingAutoBundle allows you to define automatically created routes for
13-
documents. This implies a separation of the ``Route`` and ``Content``
14-
documents. If your needs are simple this bundle may not be for you and you
15-
should have a look at :doc:`SimpleCmsBundle <simple_cms/introduction>`.
10+
The RoutingAutoBundle allows you to define automatically created routes for
11+
documents.
1612

17-
For the sake of example, we will imagine a blog application that has two
18-
routeable contents, the blog itself, and the posts for the blog. We will call
19-
these documents ``Blog`` and ``Post``, and we will class them as *content
20-
documents*.
13+
This implies a separation of the ``Route`` and ``Content`` documents. If your
14+
needs are simple this bundle may not be for you and you should have a look at
15+
:doc:`the SimpleCmsBundle <simple_cms/introduction>`.
2116

22-
.. note::
17+
Installation
18+
------------
19+
20+
You can install this bundle `with composer`_ using the
21+
`symfony-cmf/routing-auto-bundle`_ package.
2322

24-
In our example we add an auto route for the blog, but in reality, as a
25-
blog is something you create rarely, you will probably want to create
26-
routes for your blog manually, but its up to you.
23+
Features
24+
--------
2725

28-
If we create a new ``Blog`` with the title "My New Blog" the bundle could
29-
automatically create the route ``/blogs/my-new-blog``. For each new ``Post``
30-
it could create a route such as ``/blogs/my-new-blog/my-posts-title``. This
31-
URL resolves to a special type of route that we will call the *auto route*.
26+
Imagine you are going to create a forum application that has two routeable
27+
contents, a category and the topics for that forum. These documents are called
28+
``Category`` and ``Topic``, and they are called *content documents*.
3229

33-
By default, when we update a content document that has an auto route the
34-
corresponding auto route will also be updated, when deleting a content
35-
document the corresponding auto route will also be deleted.
30+
If you create a new category with the title "My New Category", the RoutingAutoBundle
31+
automatically create the route ``/forum/my-new-cateogry``. For each new ``Topic``
32+
it could create a route like ``/forum/my-new-category/my-topic-title``. This URL
33+
resolves to a special type of route that is called an *auto route*.
34+
35+
By default, when you update a content document that has an auto route, the
36+
corresponding auto route will also be updated. When deleting a content
37+
document, the corresponding auto route will also be deleted.
3638

3739
If required, the bundle can also be configured to do extra stuff, like, for
3840
example, leaving a ``RedirectRoute`` when the location of a content document
3941
changes or automatically displaying an index page when an unconfigured
40-
intermediate path is accessed (for example, listing all the children under
41-
``/blogs`` instead of returning a ``404``).
42+
intermediate path is accessed (for example, listing all the children when requesting
43+
``/forum`` instead of returning a ``404``).
4244

43-
Why not simply use a single route?
45+
Why not Simply Use a Single Route?
4446
----------------------------------
4547

46-
Of course, our fictional blog application could use a single route with a
47-
pattern ``/blogs/my-new-blog/{slug}`` which could be handled by a controller.
48-
Why not just do this?
49-
50-
1. By having a route for each page in the system the application has a
51-
knowledge of which URLs are accessible, this can be very useful, for
52-
example, when specifying endpoints for menu items are generating a site
53-
map.
54-
55-
2. By separating the route from the content we allow the route to be
56-
customized independently of the content, for example, a blog post may have
57-
the same title as another post but might need a different URL.
58-
59-
3. Separate route documents are translateable - this means we can have a URL
48+
Of course, our fictional forum application could use a single route with a
49+
pattern ``/forum/my-new-forum/{topic}``, which could be handled by a controller.
50+
Why not just do that?
51+
52+
#. By having a route for each page in the system, the application has a
53+
knowledge of which URLs are accessible. This can be very useful, for
54+
example, when specifying endpoints for menu items that are used when generating
55+
a site map;
56+
#. By separating the route from the content you allow the route to be
57+
customized independently of the content, for example, a topic may have
58+
the same title as another topic but might need a different URL;
59+
#. Separate route documents are translateable - this means you can have a URL
6060
for *each language*, "/welcome" and "/bienvenue" would each reference the
6161
same document in English and French respectively. This would be difficult
62-
if the slug were embedded in the content document.
62+
if the slug was embedded in the content document;
63+
#. By decoupling route and content the application doesn't care *what* is
64+
referenced in the route document. This means that you can easily replace the
65+
class of the document referenced.
6366

64-
4. By decoupling route and content the application doesn't care *what* is
65-
referenced in the route document. This means that we can easily replace the
66-
class of document referenced.
67+
Usage
68+
-----
6769

68-
Anatomy of an automatic URL
69-
---------------------------
70+
The diagram below shows a fictional URL for a forum topic. The first 6 elements
71+
of the URL are called the *content path*. The last element is called the *content name*.
7072

71-
The diagram below shows a fictional URL for a blog post. The first 6 elements
72-
of the URL are what we will call the *content path*. The last element we will
73-
call the *content name*.
73+
-- TODO update this image!!
7474

7575
.. image:: ../_images/bundles/routing_auto_post_schema.png
7676

@@ -80,70 +80,168 @@ tree.
8080

8181
.. note::
8282

83-
Although routes in this case can be of any document class, only objects
83+
Although routes can be of any document class in this case, only objects
8484
which extend the :class:`Symfony\\Component\\Routing\\Route` object will
8585
be considered when matching a URL.
8686

87-
The default behavior is to use Generic documents when generating a content
87+
The default behavior is to use ``Generic`` documents when generating a content
8888
path, and these documents will result in a 404 when accessed directly.
8989

90-
Internally each route stack is built up by a *builder unit*. Builder units
90+
Internally, each route stack is built up by a *builder unit*. Builder units
9191
contain one *path provider* class and two actions classes one action to take
9292
if the provided path exists in the PHPCR tree, the other if it does not. The
9393
goal of each builder unit is to generate a path and then provide a route
9494
object for each element in that path.
9595

9696
The configuration for the example above could be as follows:
9797

98-
.. code-block:: yaml
98+
.. configuration-block::
99+
100+
.. code-block:: yaml
101+
102+
# app/config/config.yml
103+
cmf_routing_auto:
104+
mappings:
105+
106+
Acme\ForumBundle\Document\Topic
107+
content_path:
108+
# corresponds first route stack in diagram: my-forum
109+
forum_path:
110+
provider: [specified, { path: my-form }]
111+
exists_action: use
112+
not_exists_action: create
113+
114+
# corresponds second route stack in diagram: my-category
115+
category_path:
116+
provider: [content_object, { method: getCategory }]
117+
exists_action: use
118+
not_exists_action: throw_exception
119+
120+
# corresponds third route stack in diagram: 2013/04/06
121+
date:
122+
provider: [content_datetime, { method: getPublishedDate } ]
123+
exists_action: use
124+
not_exists_action: create
125+
126+
# corresponds to the content name: my-topic-title
127+
content_name:
128+
provider: [content_method, { method: getTitle }]
129+
exists_action: [auto_increment, { pattern: -%d }]
130+
not_exists_action: create
131+
132+
.. code-block:: xml
133+
134+
<!-- app/config/config.xml -->
135+
<?xml version="1.0" encoding="UTF-8" ?>
136+
<container xmlns="http://symfony.com/schema/dic/services">
137+
138+
<config xmlns="http://cmf.symfony.com/schema/dic/routing_auto">
139+
140+
<mapping class="Acme\ForumBundle\Document\Topic">
141+
142+
<content-path>
143+
<!-- corresponds first route stack in diagram: my-forum -->
144+
<path-unit name="forum_path">
145+
<provider name="specified">
146+
<option name="path" value="my-forum" />
147+
</provider>
148+
</path-unit>
149+
150+
<!-- corresponds second route stack in diagram: my-category -->
151+
<path-unit name="category_path">
152+
<provider name="content_object">
153+
<option name="method" value="getCategory" />
154+
</provider>
155+
<exists-action strategy="use" />
156+
<not-exists-action strategy="throw_exception" />
157+
</path-unit>
158+
159+
<!-- corresponds third route stack in diagram: 2013/04/06 -->
160+
<path-unit name="date">
161+
<provider name="content_datetime">
162+
<option name="method" value="getPublishedDate" />
163+
</provider>
164+
</path-unit>
165+
</content-path>
166+
167+
168+
<!-- corresponds to the content name: my-topic-title -->
169+
<content-name>
170+
<provider name="content_method">
171+
<option name="method" value="getTitle" />
172+
</provider>
173+
<exists-action strategy="auto_increment">
174+
<option name="pattern" value="-%d" />
175+
</exists-action>
176+
<not-exists-action strategy="create" />
177+
</content-name>
178+
</mapping>
179+
</config>
180+
</container>
181+
182+
.. code-block:: php
99183
100-
cmf_routing_auto:
101-
102-
auto_route_mapping:
103-
My\Namespace\Bundle\BlogBundle\Document\Post:
104-
content_path:
105-
# corresponds first route stack in diagram: my, blog, my-blog
106-
blog_path:
107-
provider:
108-
name: content_object
109-
method: getBlog
110-
exists_action:
111-
strategy: use
112-
not_exists_action:
113-
strategy: throw_exception
114-
115-
# corresponds to second route stack: 2013,04,06
116-
date:
117-
provider:
118-
name: content_datetime
119-
method: getPublishedDate
120-
exists_action:
121-
strategy: use
122-
not_exists_action:
123-
strategy: create
124-
125-
# corresponds to the content name: My Post Title
126-
content_name:
127-
provider:
128-
name: content_method
129-
method: getTitle
130-
exists_action:
131-
strategy: auto_increment
132-
pattern: -%d
133-
not_exists_action:
134-
strategy: create
135-
136-
The ``Post`` document would then need to implement the methods named above as
184+
// app/config/config.php
185+
$container->loadFromExtension('cmf_routing_auto', array(
186+
'mappings' => array(
187+
'Acme\ForumBundle\Document\Topic' => array(
188+
'content_path' => array(
189+
// corresponds first route stack in diagram: my-forum
190+
'forum_path' => array(
191+
'provider' => array('specified', array(
192+
'path' => 'my-forum',
193+
)),
194+
'exists_action' => 'use',
195+
'not_exists_action' => 'create',
196+
),
197+
198+
// corresponds second route stack in diagram: my-category
199+
'category_path' => array(
200+
'provider' => array('content_object', array(
201+
'method' => 'getCategory',
202+
)),
203+
'exists_action' => 'use',
204+
'not_exists_action' => 'throw_exception',
205+
),
206+
207+
// corresponds third route stack in diagram: 2013/04/06
208+
'date' => array(
209+
'provider' => array('content_datetime', array(
210+
'method' => 'getPublishedDate',
211+
)),
212+
'exists_action' => 'use',
213+
'not_exists_action' => 'create',
214+
),
215+
),
216+
217+
// corresponds to the content name: my-topic-title
218+
'content_name' => array(
219+
'provider' => array('content_method', array(
220+
'method' => 'getTitle',
221+
)),
222+
'exists_action' => array('auto_increment', array(
223+
'pattern' => '-%d',
224+
)),
225+
'not_exists_action' => 'create',
226+
),
227+
),
228+
),
229+
));
230+
231+
The ``Topic`` document would then need to implement the methods named above as
137232
follows::
138233

139-
<?php
234+
// src/Acme/ForumBundle/Document/Topic.php
235+
namespace Acme/ForumBundle/Document;
140236

141-
class Post
237+
class Topic
142238
{
143-
public function getBlog()
239+
/**
240+
* Returns the category object associated with the topic.
241+
*/
242+
public function getCategory()
144243
{
145-
// return the blog object associated with the post
146-
return $this->blog;
244+
return $this->category;
147245
}
148246

149247
public function getPublishedDate()
@@ -153,10 +251,13 @@ follows::
153251

154252
public function getTitle()
155253
{
156-
return "My post title";
254+
return "My Topic Title";
157255
}
158256
}
159257

258+
After persisting this object, the route will be created. Of course, you need to make
259+
the properties editable and then you have a fully working routing system.
260+
160261
Path Providers
161262
--------------
162263

@@ -515,3 +616,6 @@ Note the following:
515616
* ``cmf_routing_auto.exists.action`` - if the action is to be used when a path exists;
516617
* ``cmf_routing_auto.not_exists.action`` - if the action is to be used when a path does not exist;
517618
* **Alias**: The alias of the tag is the name by which you will reference this action in the auto routing schema.
619+
620+
.. _`with composer`: http://getcomposer.org/
621+
.. _`symfony-cmf/routing-auto-bundle`: https:/packagist.org/packages/symfony-cmf/routing-auto-bundle

0 commit comments

Comments
 (0)