Blog


Construire un menu avec du contenu en base de données avec KnpMenuBundle

Le , par .

KNPMenuBundle est un Bundle qui permet de gérer assez facilement les menus d'un site web. Faire un menu statique est très simple et expliqué clairement dans la documentation. Mais parfois, le développeur a besoin de construire un menu (ou un sous-menu) en fonction de contenus en base de données. Ce billet va donc vous expliquer comment faire cela.

Le contexte

Nous allons prendre un exemple simple pour illustrer ce billet : j'ai une entité Produit avec les attributs nom et categorie, et une entité Categorie avec les attributs nom et produits. Chaque produit est relié à une catégorie.

Notre objectif est de construire un menu qui liste les catégories, et envoie l'utilisateur vers une page listant les produits de la catégorie sélectionnée.

Nous partons du principe que nous avons déjà un contrôleur qui s'occupe de lister les produits d'une catégorie. Sa route s'appelle liste_produits_categorie et elle attend un paramètre id, qui est l'identifiant de la catégorie.

Création de la classe Builder

Pour construire notre menu, il nous faut une classe Builder. Voici donc notre classe Builder par défaut :

use Knp\Menu\FactoryInterface;

class Builder
{
    public function createMainMenu(FactoryInterface $factory,
                                   array $option)
    {
        $menu = $factory->createItem('root');

        $menu->addChild(
            'categorie',
            array('label' => 'Nos produits par catégories')
        );

        // D'autres menus ensuite...

        return $menu;
    }
}

Notre objectif maintenant est de pouvoir utiliser le service Doctrine pour pouvoir faire une requête dans notre classe Builder. Pour cela, il va donc falloir transformer notre Builder en service. Ça tombe bien, la procédure est décrite dans la documentation (et en plus, l'utilisation des menus en sera aussi simplifiée).

Convertir notre classe Builder en service Symfony2

Premièrement, la documentation nous indique qu'il va falloir récupérer l'objet implémentant FactoryInterface dans le constructeur car ce dernier ne sera plus passé en argument auprès de notre fonction createMainMenu(). Dans notre cas, nous allons nous aussi avoir besoin d'un autre service : l'Entity Manager de Doctrine. Transformons donc notre classe ainsi :

use Knp\Menu\FactoryInterface;
use Doctrine\ORM\Entitymanager;

class Builder
{
    private $factory;
    private $em;

    public function __construct(FactoryInterface $factory,
                                Entitymanager $em)
    {
        $this->factory = $factory;
        $this->em = $em;
    }

    public function createMainMenu()
    {
        $menu = $this->factory->createItem('root');

        $menu->addChild(
            'categorie',
            array('label' => 'Nos produits par catégories')
        );

        // D'autres menus ensuite...

        return $menu;
    }
}

Déclarer les services dans la configuration de l'application

Il nous faut maintenant déclarer nos services auprès de Symfony2. Cela se fait dans le fichier services.yml de votre bundle, ou bien directement dans le fichier app/config/config.yml.

services:
    acme_main.menu_builder:
        class:     Acme\MainBundle\Menu\Builder
        arguments: ['@knp_menu.factory', '@doctrine.orm.entity_manager']

    acme_main.menu.main:
        class:           Knp\Menu\MenuItem
        factory_service: acme_main.menu_builder
        factory_method:  createMainMenu
        tags:
            - { name: knp_menu.menu, alias: main }

On voit bien ici que notre builder attend deux paramètres : le service Factory de KnpMenu ainsi que le service EntityManager de Doctrine. Notre builder est donc déclaré en tant que service.

Le deuxième service concerne le menu principal. En effet, on le déclare aussi comme service pour faciliter son utilisation dans les vues. Ce service fait appel à notre service Builder, et on précise la fonction appelée : createMainMenu. De cette manière, vous pouvez créer plusieurs menus au sein de votre classe Builder. Il vous suffit de déclarer deux services Menu, puis d'indiquer la bonne fonction pour l'option factory_method.

Voilà, tout est prêt maintenant pour construire notre menu en extrayant les informations de la base de données.

Construction du menu

Pour cela, rien de plus simple : nous avons l'EntityManager à notre disposition.

use Knp\Menu\FactoryInterface;
use Doctrine\ORM\Entitymanager;

class Builder
{
    private $factory;
    private $em;

    public function __construct(FactoryInterface $factory,
                                Entitymanager $em)
    {
        $this->factory = $factory;
        $this->em = $em;
    }

    public function createMainMenu()
    {
        $menu = $this->factory->createItem('root');

        $menu->addChild(
            'categorie',
            array('label' => 'Nos produits par catégories')
        );

        // Récupération de la liste des catégories.
        $listeCategories = $this->em->getRepository('AcmeMainBundle:Categorie')->find();

        // Création des sous-menus.
        foreach ($listeCategories as $categorie)
        {
            $menu['categorie']->addChild(
                'categorie_' . $categorie->getId(), // Identifiant du menu.
                array(
                    'label'           => $categorie->getNom();
                    'route'           => 'liste_produits_categorie'
                    'routeParameters' => array('id' => $categorie->getId()),
                )
            );
        }

        // D'autres menus ensuite...

        return $menu;
    }
}

Et voilà donc notre menu construit avec toutes les catégories présentes en base de données. Pour l'utiliser dans vos vues, il suffit simplement d'ajouter :

{{ knp_menu_render('main') }}

À noter que main représente l'alias que nous avons donné à notre menu dans la configuration des services.

Catégories : Blog

Retour à la liste

Commentaires

Le , a écrit :

Le , a écrit :

Le , a écrit :

Le , a écrit :

Le , a écrit :

fgh


Le , a écrit :

Le , a écrit :

Le , a écrit :

Le , a écrit :

Le , a écrit :

Le , a écrit :

Le , a écrit :

l


Le , a écrit :

yest


Le , a écrit :

Vraiment cool


Le , a écrit :

Merci beaucoup !


Le , a écrit :

Le , a écrit :

Le , a écrit :

Yaay trop bien


Le , a écrit :

Et dans le cas où on a des menus qui ont des enfants qui eux même ont des enfants... ?


Le , a écrit :

T'es sûr que c'était des corn flakes dans ton bol ? :


Le , a écrit :

Le , a écrit :

on s'éclate


Le , a écrit :

lol


Le , a écrit :

atchoum


Le , a écrit :

df


Le , a écrit :

s


Le , a écrit :

j'aime bien ce tuto


Le , a écrit :

good


Le , a écrit :

WOOOOW


Le , a écrit :

voila


Le , a écrit :

genial


Le , a écrit :

azul


Le , a écrit :

google


Le , a écrit :

merci


Le , a écrit :

thanks -- bien


Le , a écrit :

Je trouve ce bundle vraiment pratique. Merci :)


Le , a écrit :

Super article, ça nous en apprend beaucoup merci :)

n'hésitez pas à visiter mon blog :

tutoriels photoshop, design et web


Le , a écrit :

de la balleQ!!!1


Le , a écrit :

super merci


Le , a écrit :

cool


Le , a écrit :

No comment


Le , a écrit :

merci winzou


Le , a écrit :

La balise ul


Le , a écrit :

J'ai une question, comment faire pour modifier la balise

    du menu. Merci


    Le , a écrit :

    oui


    Le , a écrit :

    merci enormement


    Poster un nouveau commentaire