From 48b4edac433b055e7b57b91e46136c81e5e2b255 Mon Sep 17 00:00:00 2001 From: tiagojsag Date: Mon, 10 Dec 2012 11:19:20 +0100 Subject: [PATCH 1/3] Refactored routing --- components/routing.rst | 144 ------------------------ getting-started/overview.rst | 31 +++++ getting-started/routing.rst | 211 +++++++++++++++++++++++++++++++++++ index.rst | 14 +-- 4 files changed, 245 insertions(+), 155 deletions(-) delete mode 100644 components/routing.rst create mode 100644 getting-started/overview.rst create mode 100644 getting-started/routing.rst diff --git a/components/routing.rst b/components/routing.rst deleted file mode 100644 index c9fae910..00000000 --- a/components/routing.rst +++ /dev/null @@ -1,144 +0,0 @@ -Routing Component -================= - -The `Symfony2 CMF Routing component `_ -library extends the Symfony2 core routing component. Even though it has Symfony -in its name, it does not need the full Symfony2 framework and can be used in -standalone projects. For integration with Symfony we provide -:doc:`../bundles/routing-extra`. - -This component provides a ``ChainRouter`` that can chain several RouterInterface -instances one after the other. It uses a list of routers, ordered by a priority -value, the higher the priority number the earlier that router is asked to match -respectively generate routes. One of the routers in that chain can of course be -the Symfony2 router instance so you can still use the standard way for some of -your routes. - -Additionally, this component is meant to provide useful router implementations. -Currently, there is the ``DynamicRouter`` that routes based on a implemented -repository that provide Symfony2 Route objects. The repository can be -implemented using a database, for example with doctrine PHPCR-ODM or doctrine -orm. - -Note: To use this component outside of the Symfony2 framework context, have -a look at the core Symfony2 `Routing `_ -to get a fundamental understanding of the component. CMF Routing just extends -the basic behaviour. - -.. index:: Routing - -Dependencies ------------- - -This component uses `composer `_. It needs the -Symfony2 Routing component and the Symfony2 HttpKernel (for the logger -interface and cache warmup interface). - -For the DynamicRouter you will need something to implement the -RouteRepositoryInterface with. We suggest using Doctrine as this allows to map -any class into a database. - -ChainRouter ------------ - -The ChainRouter does not route anything on its own, but only loops through all -chained routers. Add your router instances with the ``add`` method, then try -to resolve routes with all added routers using the ``match`` method and -Please refer to the phpdoc comments on the public methods for details. - -Dynamic Router --------------- - -This implementation of a router loads routes from a RouteRepositoryInterface. -This interface can be easily implemented with doctrine. -The router works with the base UrlMatcher and UrlGenerator classes and only -adds loading routes from the database and the concept of referenced content. - -To instantiate a DynamicRouter, you need an implementation of the -RouteRepositoryInterface. See the `RoutingExtraBundle `_ -document classes for an example. - -You will want to create controller mappers that decide what controller will -be used to handle the request, to avoid hard coding controller names into your -content. - -Match Process -~~~~~~~~~~~~~ - -The match method of the DynamicRouter does the following steps - -* Ask the repository for Route documents that could match the requested url -* Build a route collection and let the UrlMatcher find a matching route -* If the defaults do not contain the field _controller, loop through the - ControllerMapperInterface list to find the controller. If none of the - mapper finds a controller, throw a ResourceNotFoundException -* If the route implements RouteObjectInterface and returns a non-null content, - set it in the returned array with key ``_content``. - - -RouteObjectInterface -~~~~~~~~~~~~~~~~~~~~ - -Routes that implement this interface can be linked to a content document using -the ``getRouteContent`` method. If non-null, this content is passed to the -controller. If there is no specific content for this route this may return null. - -Furthermore, routes that implement this interface can also provide a custom route -name. The key returned by ``getRouteKey`` will be used as route name instead of -the Symfony core compatible route name and can contain any characters. This allows -you, for example, to set a path as the route name. - -All routes still need to extend the base class ``Symfony\Component\Routing\Route`` - -Redirections -~~~~~~~~~~~~ - -You can build redirections with a RedirectRouteInterface document. It can -redirect either to an absolute URI, or to a named route that can be generated by -any router in the chain or to another Route object in the repository. -To handle it, you can make ControllerClassMapper map a suitable controller -to ``Symfony\Cmf\Component\Routing\RedirectRouteInterface`` - -Routes and locales -~~~~~~~~~~~~~~~~~~ - -You can use the _locale default value in a route to create one route per locale -that all reference the same multilingual content. -The DynamicRouter respects the _locale when generating routes from content. -When resolving the route, the _locale gets into the request and is picked up -by the Symfony2 locale system. - -A note for PHPCR-ODM: Routes should never be translatable documents, as one -route document represents one single url, and serving several translations -under the same url is not a good idea. - - -Customize -~~~~~~~~~ - -You can add more ControllerMapperInterface implementations if you have a case -not handled by the provided ones. - -For more specific needs, have a look at DynamicRouter and see if you want to -extend it. You can also write your own routers to hook into the chain. - -Url generation -~~~~~~~~~~~~~~ - -You can generate urls for your content in three ways: - -* Either pass an implementation of RouteObjectInterface as parameter ``route`` -* Or pass a content object as parameter ``content`` -* Or supply an implementation of ContentRepositoryInterface and the id of the content as parameter ``content_id`` - -Authors -------- - -* Filippo De Santis (p16) -* Henrik Bjornskov (henrikbjorn) -* Claudio Beatrice (omissis) -* Lukas Kahwe Smith (lsmith77) -* David Buchmann (dbu) -* `And others `_ - -The original code for the chain router was contributed by Magnus Nordlander. diff --git a/getting-started/overview.rst b/getting-started/overview.rst new file mode 100644 index 00000000..0a1079b4 --- /dev/null +++ b/getting-started/overview.rst @@ -0,0 +1,31 @@ +Overview +======== + +This guide will help you understand the basic parts of Symfony CMF and how +they work together to provide the default pages you can see when browsing +the Symfony CMF Standard Edition (SE) installation. + +It assumes you have already installed Symfony CMF and have carefully +read the Symfony2 book. + +AcmeMainBundle and SimpleCMSBundle +---------------------------------- + +Symfony CMF SE comes with a default AcmeMainBundle to help you get started, +in a similar way that Symfony2 has AcmeDemoBundle, providing you some +demo pages visible on your browser. However, AcmeMainBundle doesn't include +controllers or configuration files, like you probably would expect. It contains +little more than a twig file and `Fixtures `_ +data, that was loaded into your database during installation. + +There are several bundles working together in order to turn the fixture data +into a browsable website. The overall, simplified process is: + +- When a request is received, the Symfony CMF :doc:`routing`'s Dynamic Router is used to handle the incoming request. +- The Dynamic Router is able to match the requested URL with a specific ContentBundle's Content stored in the database. +- The retrieved content's information is used to determine which controller to pass it on to, and which template to use. +- As configured, the retrieved content is passed to ContentBundle's ContentController, which will handle it and render AcmeMainBundle's layout.html.twig. + + Again, this is simplified view of a very simple CMS built on top of Symfony CMF. + To fully understand all the possibilities of the CMF, a carefull look into + each component is needed. \ No newline at end of file diff --git a/getting-started/routing.rst b/getting-started/routing.rst new file mode 100644 index 00000000..9b371504 --- /dev/null +++ b/getting-started/routing.rst @@ -0,0 +1,211 @@ +Routing Component +================= + +The `Symfony CMF Routing component `_ +library extends the Symfony2 core routing component. Even though it has Symfony +in its name, it does not need the full Symfony2 framework and can be used in +standalone projects. For integration with Symfony we provide +:doc:`../bundles/routing-extra`. + +At the core of the Symfony CMF Routing component is the ``ChainRouter``, that +is used instead of the Symfony2's default routing system. The ChainRouter +can chain several ``RouterInterface`` implementations, one after the other, +to determine who should handle each request. The default Symfony2 router +can be added to this chain, so the standard routing mechanism can still be +used. + +Additionally, this component is meant to provide useful ``RouterInterface`` +implementations. Currently, it provides ``DynamicRouter`` that's able to +dynamically retrieve a Symfony2 Route object from a repository. The repository +can be implemented using a database, for example with Doctrine PHPCR-ODM +or Doctrine ORM. + +.. note:: + + To use this component outside of the Symfony2 framework context, have + a look at the core Symfony2 `Routing `_ + to get a fundamental understanding of the component. CMF Routing just extends + the basic behaviour. + +.. index:: Routing + +Dependencies +------------ + +This component uses `composer `_. It needs the +Symfony2 Routing component and the Symfony2 HttpKernel (for the logger +interface and cache warmup interface). + +For the DynamicRouter you will need something to implement the +RouteRepositoryInterface with. We suggest using Doctrine as this allows to map +any class into a database. + +ChainRouter +----------- + +At the core of Symfony CMF's Routing component sits the ``ChainRouter``. +It's used as a replacement for Symfony2's default routing system, and is +responsible for determining which Controller will handle each request. + +The ``ChainRouter`` works by accepting a set of prioritized routing strategies, +`RouterInterface `_ +implementations, commonly referred to as "Routers". + +When handling an incoming request, it will iterate over the configured Routers, +by their configured priority, until one of them is able to `match `_ +the request and assign the request to a given Controller. + +Routers +------- + +The ``ChainRouter`` is incapable of, by itself, making any actual routing. +It's sole responsibility is managing the given set of Routers, which are the +true responsibles for the matching a request to a Controller. + +You can easily create your own Routers by implementing `RouterInterface `_ +but, by default, Symfony CMF already includes some basic routing mechanism to +help you get started. + +.. note:: + + If you are using this as part of a full Symfony CMF project, please refer to + :doc:`../bundles/routing-extra` for instructions on how to add Routers to + the ``ChainRouter``. Otherwise, use the ``ChainRouter``'s ``add`` method to + configure new Routers. + +Symfony2 Default Router +~~~~~~~~~~~~~~~~~~~~~~~ + +The Symfony2 routing mechanism is itself a ``RouterInterface`` implementation, +which means you can use it as a Router in the ``ChainRouter``. This allows you +to use the default routing declaration system. + +Dynamic Router +~~~~~~~~~~~~~~ + +The DynamicRouter is capable of loading `Route `_ +objects dynamically from a given data source provided to the Router as a +``RouteRepositoryInterface`` implementation. Although it can be used in other +ways, the ``RouteRepositoryInterface``'s main goal is to be easily implementented +on top of Doctrine PHPCR ODM, effectively allowing you to store and manage +routes dynamically from database. + +Request handling +^^^^^^^^^^^^^^^^ + +The incoming request are handled by the ``DynamicRouter``'s ``match`` +using the following workflow: + +* The ``DynamicRouter`` uses the ``RouteRepositoryInterface`` to fetch a set of ``Route`` instances +* The ``UrlMatcher`` is then used on the returned set to find a single matching ``Route`` +* A set of optional ``RouteEnhancers`` is applied to the ``Route`` + +The Fetching +"""""""""""" + +Based on the requested url, the ``DynamicRouter`` will retrieve a ordered +set of ``Route`` objects from the ``RouteRepositoryInterface``. + +The underlying implementation of the ``RouteRepositoryInterface`` interface +is not part of this bundle's scope. Refer to the interface declaration for +more information. For a functional example, see `RoutingExtraBundle `_. + +The Matching +"""""""""""" + +The DynamicRouter uses Symfony Routing Component's `UrlMatcher `_ +when iterating over the retrieved ``Route`` objects, in order to determine +which of them to use. + +The Enhancers +""""""""""""" + +Optionally, a set of ``RouteEnhancerInterface`` instances can be declared and +associated with the DynamicRouter. The aim of these is to allow you to manipulate +the ``Route`` and its associated parameters. They can be used, for example, +to dynamically assign a controller or template to a ``Route``. Some simple +Enhancers are already packed with the bundle, documentation can be found +inside each class file. + +Linking a Route with a Document +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Depending on you application's logic, a requested url may have an associated +Document from the database. Those Routes should implement the ``RouteObjectInterface``, +and can optionally return a Document object, that will be bundled in the +returned array, in the ``_content`` key. Notice that a Route can implement +the above mentioned interface but still not to return any object, in which +case no associated Document will be returned. + +Furthermore, routes that implement this interface can also provide a custom Route +name. The key returned by ``getRouteKey`` will be used as route name instead of +the Symfony core compatible route name and can contain any characters. This allows +you, for example, to set a path as the route name. + +All routes still need to extend the base class ``Symfony\Component\Routing\Route`` + +Redirections +^^^^^^^^^^^^ + +You can build redirections by implementing the ``RedirectRouteInterface``. +It can redirect either to an absolute URI, to a named Route that can be +generated by any Router in the chain or to another Route object in the repository. + +Notice that the actual redirection logic is not handled by the bundle. You +should implement your own logic to handle the actual redirection. For an +example on implementing that redirection under the full Symfony2 stack, refer +to :doc:`../bundles/routing-extra`. + +Routes and locales +^^^^^^^^^^^^^^^^^^ + +You can use the ``_locale`` default value in a Route to create one Route +per locale that, all referencing the same multilingual content. The ``DynamicRouter`` +respects the ``_locale`` when generating routes from content. When resolving +the route, the _locale gets into the request and is picked up by the Symfony2 +locale system. + +.. note:: + + Under PHPCR-ODM, Routes should never be translatable documents, as one + Route document represents one single url, and serving several translations + under the same url is not recommended. + + +Url generation +^^^^^^^^^^^^^^ + +``DynamicRouter`` uses Symfony2's default `UrlGenerator `_ +to handle url generation. You can generate urls for your content in three ways: + +* Either pass an implementation of ``RouteObjectInterface`` as ``route`` parameter +* Or pass a content object as ``content`` parameter +* Or supply an implementation of ``ContentRepositoryInterface`` and the id of the content as parameter ``content_id`` + +Customization +------------- + +The Routing bundles allows for several cutomization options, depending on +your specific needs: + +* Your Route parameters can be easily manipulated using the exiting Enhancers +* Yuo can also add your own Enhancers to the Router logic. +* The ``DynamicRouter`` or its components can be extended to allow modifications +* You can implement your own Routers and add them to the ``ChainRouter`` + +.. note:: + + If you feel like your specific Enhancer or Router can be usefull to others, + get in touch with us and we'll try to include it in the bundle itself + +Authors +------- + +* Filippo De Santis (p16) +* Henrik Bjornskov (henrikbjorn) +* Claudio Beatrice (omissis) +* Lukas Kahwe Smith (lsmith77) +* David Buchmann (dbu) +* `And others `_ + +The original code for the chain router was contributed by Magnus Nordlander. diff --git a/index.rst b/index.rst index c9850d45..2bfdcae4 100644 --- a/index.rst +++ b/index.rst @@ -1,4 +1,4 @@ -Symfony CMF Documentation +Symfony CMF Documentation ========================= Welcome to the official documentation of the `Symfony Content Management Framework`_. @@ -52,6 +52,8 @@ Just started learning about the CMF? Want to know if the CMF fits your project? :maxdepth: 1 getting-started/installing-symfony-cmf + getting-started/overview + getting-started/routing Tutorials @@ -105,16 +107,6 @@ Special solutions for special needs that go beyond standard usage. cookbook/using-a-custom-route-repository cookbook/installing-cmf-sandbox -Components ----------- - -Looking for some for information about the low level components of the CMF? - -.. toctree:: - :maxdepth: 1 - - components/routing - Contributing ------------ From 01766cb01e0475e13911b0974f8009a6bcca43a5 Mon Sep 17 00:00:00 2001 From: tiagojsag Date: Mon, 10 Dec 2012 11:29:14 +0100 Subject: [PATCH 2/3] added Symfony2 integration to routing --- getting-started/routing.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/getting-started/routing.rst b/getting-started/routing.rst index 9b371504..5581e687 100644 --- a/getting-started/routing.rst +++ b/getting-started/routing.rst @@ -198,6 +198,14 @@ your specific needs: If you feel like your specific Enhancer or Router can be usefull to others, get in touch with us and we'll try to include it in the bundle itself +Symfony2 integration +-------------------- + +Like mentioned before, this bundle was designed to only require certain parts +of Symfony2. However, if you wish to use it as part of your Symfony CMF project, +an integration bundle is also available. We strongly recommend that you take +a look at :doc:`../bundles/routing-extra`. + Authors ------- From 62cd1f5063f044397853d355c1c8c85ca18f991a Mon Sep 17 00:00:00 2001 From: tiagojsag Date: Mon, 10 Dec 2012 15:37:29 +0100 Subject: [PATCH 3/3] Moved routing back to "component" section. Naming changes --- {getting-started => components}/routing.rst | 30 ++++++++++----------- index.rst | 11 +++++++- 2 files changed, 25 insertions(+), 16 deletions(-) rename {getting-started => components}/routing.rst (89%) diff --git a/getting-started/routing.rst b/components/routing.rst similarity index 89% rename from getting-started/routing.rst rename to components/routing.rst index 5581e687..3af6c74e 100644 --- a/getting-started/routing.rst +++ b/components/routing.rst @@ -36,8 +36,8 @@ This component uses `composer `_. It needs the Symfony2 Routing component and the Symfony2 HttpKernel (for the logger interface and cache warmup interface). -For the DynamicRouter you will need something to implement the -RouteRepositoryInterface with. We suggest using Doctrine as this allows to map +For the ``DynamicRouter`` you will need something to implement the +``RouteRepositoryInterface`` with. We suggest using Doctrine as this allows to map any class into a database. ChainRouter @@ -83,7 +83,7 @@ to use the default routing declaration system. Dynamic Router ~~~~~~~~~~~~~~ -The DynamicRouter is capable of loading `Route `_ +The ``DynamicRouter`` is capable of loading `Route `_ objects dynamically from a given data source provided to the Router as a ``RouteRepositoryInterface`` implementation. Although it can be used in other ways, the ``RouteRepositoryInterface``'s main goal is to be easily implementented @@ -127,22 +127,22 @@ to dynamically assign a controller or template to a ``Route``. Some simple Enhancers are already packed with the bundle, documentation can be found inside each class file. -Linking a Route with a Document -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Linking a Route with a Content +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Depending on you application's logic, a requested url may have an associated -Document from the database. Those Routes should implement the ``RouteObjectInterface``, -and can optionally return a Document object, that will be bundled in the +content from the database. Those Routes should implement the ``RouteObjectInterface``, +and can optionally return a model instance, that will be bundled in the returned array, in the ``_content`` key. Notice that a Route can implement -the above mentioned interface but still not to return any object, in which -case no associated Document will be returned. +the above mentioned interface but still not to return any model instance, +in which case no associated object will be returned. Furthermore, routes that implement this interface can also provide a custom Route name. The key returned by ``getRouteKey`` will be used as route name instead of the Symfony core compatible route name and can contain any characters. This allows you, for example, to set a path as the route name. -All routes still need to extend the base class ``Symfony\Component\Routing\Route`` +All routes still need to extend the base class ``Symfony\Component\Routing\Route``. Redirections ^^^^^^^^^^^^ @@ -160,9 +160,9 @@ Routes and locales ^^^^^^^^^^^^^^^^^^ You can use the ``_locale`` default value in a Route to create one Route -per locale that, all referencing the same multilingual content. The ``DynamicRouter`` -respects the ``_locale`` when generating routes from content. When resolving -the route, the _locale gets into the request and is picked up by the Symfony2 +per locale that, all referencing the same multilingual model instance. The ``DynamicRouter`` +respects the ``_locale`` when generating routes from model instances. When resolving +the route, the ``_locale`` gets into the request and is picked up by the Symfony2 locale system. .. note:: @@ -179,8 +179,8 @@ Url generation to handle url generation. You can generate urls for your content in three ways: * Either pass an implementation of ``RouteObjectInterface`` as ``route`` parameter -* Or pass a content object as ``content`` parameter -* Or supply an implementation of ``ContentRepositoryInterface`` and the id of the content as parameter ``content_id`` +* Or pass a model instance as ``content`` parameter +* Or supply an implementation of ``ContentRepositoryInterface`` and the id of the model instance as parameter ``content_id`` Customization ------------- diff --git a/index.rst b/index.rst index 2bfdcae4..ce596999 100644 --- a/index.rst +++ b/index.rst @@ -53,7 +53,6 @@ Just started learning about the CMF? Want to know if the CMF fits your project? getting-started/installing-symfony-cmf getting-started/overview - getting-started/routing Tutorials @@ -106,6 +105,16 @@ Special solutions for special needs that go beyond standard usage. cookbook/phpcr-odm-custom-documentclass-mapper cookbook/using-a-custom-route-repository cookbook/installing-cmf-sandbox + +Components +---------- + +Looking for some for information about the low level components of the CMF? + +.. toctree:: + :maxdepth: 1 + + components/routing Contributing ------------