31 December 2014

Créer des menus KnpMenu – Symfony2 pour les nuls

Hello !

Le menu est un élément primordial dans la construction d’un site, je ne vous apprend rien. Il est la brique maitresse qui organisera le site et permettra à votre visiteur de naviguer. Réussir son menu est donc extremement important, c’est pourquoi j’écris cet article aujourd’hui :

Nous allons utiliser le menu KnpMenu.

Pour cela, suivez les étapes :

 

Installation :

Etape 1 : Obtenir le bundle et la librairie

Récupérez la librairie KnpMenu et le bundle KnpMenuBundle via composer :

« knplabs/knp-menu »: « dev-master »,
« knplabs/knp-menu-bundle »: « dev-master »,

 

Etape 2 : Déclarer le bundle

C’est bien sur dans le AppKernel que ca se passe :

<?php
// app/AppKernel.php

public function registerBundles()
{
    $bundles = array(
        // ...
        Knp\Bundle\MenuBundle\KnpMenuBundle(),
    );
    // ...
}

 

Philosophie de la librairie :

Les créateurs de la librairie ont une excellente approche de ce que doit être un menu et l’architecture donnée permet de faire un grand nombre de chose, on verra ca plus bas. Un menu est un lui-même un élément de menu (MenuItem) qui peut avoir des enfants, eux aussi de la classe MenuItem, donc qui peuvent aussi avoir des enfants et ce, évidement, sans limite. Le menu est créé par un MenuBuilder que nous créerons à l’aide des services qui soit dit en passant est un don de dieu.

Ci-dessous notre MenuBuilder :

<?php
// src/Acme/MainBundle/Menu/MenuBuilder.php

namespace AcmeMainBundleMenu;

use KnpMenuFactoryInterface;
use SymfonyComponentHttpFoundationRequest;

class MenuBuilder
{
    private $factory;

    /**
     * @param FactoryInterface $factory
     */
    public function __construct(FactoryInterface $factory)
    {
        $this->factory = $factory;
    }

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

        $menu->addChild('Home', array('route' => 'homepage'));
        // ... ajoutez ici les autres liens de base

        return $menu;
    }
}

Ensuite, créons deux services, un pour le MenuBuilder et l’autre pour le menu que l’on va créer :

# src/Acme/MainBundle/Resources/config/services.yml
services:
    acme_main.menu_builder:
        class: AcmeMainBundleMenuMenuBuilder
        arguments: ["@knp_menu.factory"]

    acme_main.menu.main:
        class: KnpMenuMenuItem
        factory_service: acme_hello.menu_builder
        factory_method: createMainMenu
        arguments: ["@request"]
        scope: request
        tags:
            - { name: knp_menu.menu, alias: main } # L'alias est très important, c'est avec lui que vous appellerez votre menu dans la vue

On peut dès maintenant afficher le menu en écrivant le code ci-dessous dans n’importe quelle vue TWIG :

{{ knp_menu_render('main') }}

 

One more thing…

Dans l’usage, comment l’utilisons nous ?

Pour ma part, la plupart du temps, mon menu est statique, contrairement à mon breadcrumb qui lui est dynamique selon la page ou l’on se trouve; un menu quant à lui est assez statique et c’est souvent seulement la page courante qui varie.

Je créé donc le menu comme au dessus, en ajoutant toute l’architecture du menu, avec les pages de niveaux inférieurs le cas échant.

Ensuite, pour définir la page courante, ou finalement pour faire n’importe quelle modification sur le menu, j’ai simplement à récupérer mon menu comme n’importe quel service dans mon controller :

# src/Acme/MainBundle/Controller/HomeController.php
public function HomeAction() {
        $menu = $this->get("acme_main.menu.main");
        $menu->getChild("home")->setCurrent(true);
        ...
}
Easy mode !
May the force be with you ;)
comments powered by Disqus