The menu documents are only used for persisting the menu data, they are not
actually used when rendering a menu. Menu items are the objects that are needed
to render a menu. A menu factory creates such menu items from the menu
nodes provided by the menu provider.
New in version 2.0: Adding content support to the knp_menu.factory service was introduced
in CmfMenuBundle 2.0. Prior to 2.0, you had to use the
ContentAwareFactory class and cmf_menu.factory service.
Most menu items will need a URL. By default, KnpMenu allows generating this URL
by specifying a URI or a Symfony route name.
The CmfMenuBundle provides another way to generate URLs: By using the
dynamic router to generate routes
from content objects.
The content menu node option, if specified, must contain something that the
content URL generator can work with. When using the dynamic router, this needs to be a class implementing the
When you don’t use the dynamic router, you can create a custom url
generator by implementing UrlGeneratorInterface and configure it using
the content_url_generator option in config.yml.
New in version 1.2: The content_url_generator option was introduced in CmfMenuBundle 1.2.
When menu nodes refer to content that has been deleted or there is another
error during route generation, a menu node is skipped by default. You can set
the allow_empty_items setting of the CmfMenuBundle to true to render
these nodes as plain text instead.
The CmfMenuBundle provides a MenuContentVoter, which checks if the
referenced content is published using the
publish workflow checker. If the content is
not yet published, the menu item not will not be rendered.
The CmfMenuBundle dispatches a cmf_menu.create_menu_item_from_node event
during the process of creating a menu item from a menu node. You can use this
event to control the MenuItem that is created and to mark the current node
or its children as skipped.
Listeners for this method receive a CreateMenuItemFromNodeEvent instance,
which provides access to node using the getNode() method and allows
skipping nodes using the setSkipNode() and setSkipChildren() methods.
If you mark the Menu document (the root node of each menu) as skipped,
an empty item is still created to avoid errors when rendering a menu.
You can use the setItem() method to set the menu item to use instead of one
generated using the menu node. The child nodes are still processed like normal
and added to this new item.
You can inject the knp_menu.factory service in the listener to generate
new menu items from nodes.