No CMS system is complete without a menu system that allows users to navigate
between content pages and perform certain actions. While it usually maps
the actual content tree structure, menus often have a logic of their own,
include options not mapped by content or exist in multiple contexts with
multiple options, thus making them a complex problem themselves.
Symfony CMF SE includes the MenuBundle, a tool that allow you to dynamically
define your menus. It extends the KnpMenuBundle, with a set of
hierarchical, multi language menu elements, along with the tools to persist
them in the chosen content store. It also includes the administration panel
definitions and related services needed for integration with the
The MenuBundle extends and greatly relies on the KnpMenuBundle, so you
should carefully read KnpMenuBundle's documentation. For the rest of
this page we assume you have done so and are familiar with concepts like
Menu Providers and Menu Factories.
The core of the MenuBundle is PhpcrMenuProvider, a
MenuProviderInterface implementation that's responsible for dynamically
loading menus from a PHPCR database. The default provider service is
configured with a menu_basepath to know where in the PHPCR tree it will
find menus. The menu name is given when rendering the menu and must be a
direct child of the menu base path. This allows the PhpcrMenuProvider to
handle several menu hierarchies using a single storage mechanism.
To give a concrete example, if we have the configuration as given below and
render the menu simple, the menu root node must be stored at
Menu factories generate the full MenuItem hierarchy from the provided
menu node. The data generated this way is later used to generate the actual
HTML representation of the menu.
The included implementation focuses on generating MenuItem instances from
NodeInterface instances, as this is usually the best approach to handle
tree-like structures typically used by a CMS. Other approaches are implemented in
the base classes and their respective documentation pages can be found in
KnpMenu already includes a specific factory targeted at the Symfony Routing
component to add support for:
As mentioned before, the factory is responsible for loading all the menu nodes
from the provided root element. The actual loaded nodes can be of any class,
even if it's different from the root's, but all must implement
NodeInterface in order to be included in the generated menu.
Also included in the MenuBundle is the MenuNode document. If you have
read the documentation page regarding Static Content, you'll find
this implementation somewhat familiar.
MenuNode implements the above mentioned NodeInterface, and holds the
information regarding a single menu entry: a label and a uri, a
children list, plus some attributes for the node
and its children that will allow the rendering process to be
customized. It also includes a Route field and two references to
Contents. These are used to store an associated Route object, plus one
(not two, despite the fact that two fields exist) Content element. The
MenuNode can have a strong (integrity ensured) or weak (integrity not
ensured) reference to the actual Content element it points to; it's up to you
to choose which best fits your scenario. You can find more information on
references on the Doctrine PHPCR documentation page.
The MenuBundle also includes the administration panels and respective services
needed for integration with the backend admin tool
The included administration panels are automatically available but need to
be explicitly put on the dashboard if you want to use them. See
The Backend - Sonata Admin for instructions on how to install