Ningún sistema CMS está completo sin un sistema de menús que permita a los usuarios navegar entre las páginas de contenido y realizar determinadas acciones. Si bien, normalmente asignan el contenido real en una estructura de árbol, los menús a menudo tienen su propia lógica, incluyendo opciones no asignadas al contenido o existentes en múltiples contextos con múltiples opciones, por ello volviéndolos un problema complejo.
La EE del CMF de Symfony incluye el MenuBundle, una herramienta que te permite definir tus menús dinámicamente. It extends KnpMenuBundle, with a set of hierarchical, multi language menu elements, along with the tools to load and store them from/to a database. It also includes the administration panel definitions and related services needed for integration with SonataDoctrinePhpcrAdminBundle
Nota
El MenuBundle extiende y en gran medida depende del KnpMenuBundle, por lo tanto tienes que leer cuidadosamente la documentación del KnpMenuBundle. Para el resto de esta página se supone que has leido dicha documentación, y estás familiarizado con conceptos como proveedores de menús y factorías de menús.
De manera predeterminada el MenuBundle usa los reproductores y ayudantes del KnpMenuBundle para imprimir tus menús. Puedes consultar la página de documentación respectiva para más información sobre el tema, pero una llamada básica sería:
{{ knp_menu_render('simple') }}
<?php echo $view['knp_menu']->render('simple') ?>
El nombre del menú proporcionado será pasado a la implementación de la MenuProviderInterface, la cual lo utilizará para identificar qué menú quieres dibujar en esa sección específica.
El núcleo del MenuBundle es PHPCRMenuProvider, una implementación de la MenuProviderInterface que es responsable de cargar menús dinámicamente desde una base de datos PHPCR. 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 /cms/menu/simple.
symfony_cmf_menu:
menu_basepath: /cms/menu
<symfony-cmf-menu:config>
<symfony-cmf-menu:menu-basepath>/cms/menu</symfony-cmf-menu:menu-basepath>
</symfony-cmf-menu:config>
$container->loadFromExtension('symfony_cmf_menu', array(
'menu_basepath' => '/cms/menu',
));
If you need multiple menu roots, you can create further PHPCRMenuProvider instances and register them with KnpMenu - see the CMF MenuBundle DependencyInjection code for the details.
El elemento del menú recuperado usando este proceso se utiliza como el nodo raíz del menú, y sus hijos serán cargados progresivamente conforme el MenuFactory vaya dibujando la estructura del menú completo.
The ContentAwareFactory is a FactoryInterface implementation, which generates the full MenuItem hierarchy from the provided MenuNode. Los datos generados de este modo se utilizan más tarde para generar la representación HTML real del menú.
La implementación incluida se enfoca en generar instancias de MenuItem a partir de instancias de NodeInterface, puesto que esa es la mejor aproximación para manejar estructuras estilo árbol como las utilizadas típicamente por los CMS. Other approaches are implemented in the base classes, and their respective documentation pages can be found in KnpMenuBundle‘s page.
ContentAwareFactory is responsible for loading the full menu hierarchy and transforming the MenuNode instances from the root node it receives from the MenuProviderInterface implementation. También es responsable de determinar cuál elemento del menú (si lo hay) está viendo el usuario actualmente. KnpMenu ya incluye una factoría específica apuntada en el componente de enrutado de Symfony2, la cual extiende este paquete, para añadir el soporte necesario para:
Como se mencionó antes, la ContentAwareFactory es responsable de cargar todos los nodos del menú a partir del elemento raíz proporcionado. Los nodos cargados realmente pueden ser de cualquier clase, incluso si son diferentes de la clase del nodo raíz, pero todos tienen que implementar la NodeInterface para poder incluirlos en el menú generado.
Además, incluidos en el MenuBundle vienen dos tipos de nodos de contenido del menú: MenuNode y MultilangMenuNode. Si leíste la página de documentación relativa al Contenido, encontrarás un tanto familiar esta implementación. El MenuNode Implementa la NodeInterface mencionada arriba, y mantiene la información relacionada a una sola entrada del menú: Una etiqueta y una uri, una lista de hijos, tal como esperarías, más algunos atributos para él y sus hijos, mismos que te permiten personalizar el proceso de reproducción real. También incluye un campo Route y dos referencias al Contenido. Estas se usan para almacenar un objeto Route asociado, más un elemento (no dos, a pesar del hecho de que existen dos campos) de Contenido. El MenuNode puede tener una referencia fuerte (garantizando la integridad) o débil (sin garantizar la integridad) al elemento de Contenido real al que apunta, tu trabajo es elegir la que sea más adecuada en tu escenario. Puedes encontrar más información y referencias en la página de la documentación del PHPCR de Doctrine.
MultilangMenuNode extiende al MenuNode con apoyo multilingüe. Añade un campo locale para identificar qué traducción pertenece a cada menú, más una etiqueta y una uri en los campos marcados como translated=true, lo cual significa que diferirán entre traducciones, a diferencia de los otros campos.
También especifica la estrategia utilizada para almacenar múltiples traducciones en la base de datos:
/**
* @PHPCRODM\Document(translator="attribute")
*/
For information on the available translation strategies, refer to the Doctrine page regarding Multi language support in PHPCR-ODM
MenuBundle also includes the administration panels and respective services needed for integration with the backend admin tool SonataDoctrinePhpcrAdminBundle
The included administration panels will automatically available but need to be explicitly put on the dashboard if you want to use them. See Creando un CMS con CMF y Sonata for instructions on how to install SonataDoctrinePhpcrAdminBundle.
Este paquete se configura usando un conjunto de parámetros, pero todos ellos son opcionales. You can go to the MenuBundle reference page for the full configuration options list and additional information.
Para más información sobre el MenuBundle del CMF de Symfony, por favor consulta: