diff --git a/components/routing.rst b/components/routing.rst index c9fae910..3af6c74e 100644 --- a/components/routing.rst +++ b/components/routing.rst @@ -1,29 +1,31 @@ Routing Component ================= -The `Symfony2 CMF 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 +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. +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 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. +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. +.. 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 @@ -34,102 +36,175 @@ 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 ----------- -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. +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. -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. +Request handling +^^^^^^^^^^^^^^^^ -To instantiate a DynamicRouter, you need an implementation of the -RouteRepositoryInterface. See the `RoutingExtraBundle `_ -document classes for an example. +The incoming request are handled by the ``DynamicRouter``'s ``match`` +using the following workflow: -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. +* 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`` -Match Process -~~~~~~~~~~~~~ +The Fetching +"""""""""""" -The match method of the DynamicRouter does the following steps +Based on the requested url, the ``DynamicRouter`` will retrieve a ordered +set of ``Route`` objects from the ``RouteRepositoryInterface``. -* 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``. +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 +"""""""""""" -RouteObjectInterface -~~~~~~~~~~~~~~~~~~~~ +The DynamicRouter uses Symfony Routing Component's `UrlMatcher `_ +when iterating over the retrieved ``Route`` objects, in order to determine +which of them to use. -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. +The Enhancers +""""""""""""" -Furthermore, routes that implement this interface can also provide a custom route +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 Content +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Depending on you application's logic, a requested url may have an associated +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 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 -~~~~~~~~~~~~ +^^^^^^^^^^^^ -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`` +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 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. +You can use the ``_locale`` default value in a Route to create one Route +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. -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. +.. 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. -Customize -~~~~~~~~~ -You can add more ControllerMapperInterface implementations if you have a case -not handled by the provided ones. +Url generation +^^^^^^^^^^^^^^ -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. +``DynamicRouter`` uses Symfony2's default `UrlGenerator `_ +to handle url generation. You can generate urls for your content in three ways: -Url generation -~~~~~~~~~~~~~~ +* Either pass an implementation of ``RouteObjectInterface`` as ``route`` parameter +* 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 +------------- + +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 -You can generate urls for your content in three ways: +Symfony2 integration +-------------------- -* 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`` +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 ------- 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/index.rst b/index.rst index c9850d45..ce596999 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,7 @@ 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 Tutorials @@ -104,7 +105,7 @@ 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 ----------