Comment gérer la navigation de son site avec le Zend Framework

glossy-navigation-menu-preview

Dans ce tuto on va voir comment mettre en place un système automatique de navigation dans le Zend Framework. C’est a dire que notre menu de navigation soit dynamique et flexible. On pourra par exemple avoir notre chemin de navigation ou fil de navigation. On va donc utiliser le composant Zend_Navigation. On a plusieurs possibilité pour la gestion et le stockage de l’arbre (ou graphe) de navigation. Moi j’ai choisit le XML pour le stockage, et la gestion par module, controller et action. Enfin on utilise aussi la traduction automatique ;)

Sommaire

Introduction

On commence par un aperçu de notre fichier de navigation :

<?xml version="1.0" encoding="UTF-8"?>
<configdata>
<nav>
	<home>
		<label>nav_home</label>
		<controller>index</controller>
	</home>
</nav>
</configdata>

Petite explication : la balise configdata ne sert que de nœud racine, la balise nav sert a repérer notre section de la gestion de la navigation. Dans mon cas je n’utilise le fichier navigation.xml que pour gérer la navigation, pour on pourrait envisager de n’avoir qu’un seul gros fichier xml pour gérer toutes nos données et variables de l’application.
Ensuite on a une balise home, elle représente un lien du menu, on lui donne le nom qu’on veut, elle va représenter dans notre cas la page d’accueil. Elle a pour classe fille une balise label qui définit le nom du lien. J’utilise nav_home car dans mon fichier de traduction j’ai une clé nav_home qui fait référence a home. Enfin il y a une balise controller qui définit sur quel controller pointe le futur lien. Il est bien sur possible de sélectionner une action avec la balise action et un module avec la balise module. C’est bien fait non ? Sinon il est possible aussi d’avoir un liens direct grâce a la balise uri. Un petit exemple qui regroupe tout les cas :

<?xml version="1.0" encoding="UTF-8"?>
<configdata>
<nav>
	<home>
		<label>nav_home</label>
		<controller>index</controller>
	</home>
	<page2>
		<label>Page 2</label>
		<module>mon_module</module>
		<controller>mon_controller</controller>
		<action>mon_action</action>
	</home>
	<home>
		<label>nav_home</label>
		<uri>/foo/bar/</uri>
	</home>
</nav>
</configdata>

Bootstrap

Il faut rajouter une méthode a notre bootstrap :

	/**
	 * @return Zend_Navigation
	 */
	protected function _initNavigation()	{
		$view = $this->bootstrap('layout')->getResource('layout')->getView();
		$config = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml', 'nav');
		$view->navigation(new Zend_Navigation($config));
	}

La seule chose a retenir ici est le premier argument de la méthode Zend_Config_Xml : c’est le chemin de notre fichier de navigation et le deuxième argument représente la balise mère de notre section de navigation dans le fichier xml.
Voilà, on a notre fonction de navigation disponible dans notre application. Il suffit maintenant de l’utiliser.

Layout

Histoire de faire le plus simple possible, on va ajouter notre barre de navigation directement dans le layout, histoire de le retrouver sur toutes les pages. Il suffit de rajouter ce bout de code dans le fichier layout.phtml à l’endroit ou vous voulez que le menu s’affiche :

<?php echo $this->navigation()->menu(); ?>

Hiérarchie de pages

On va voir maintenant un exemple de fichier xml ou il y a plusieurs pages et sous pages
navigation-Menu

<?xml version="1.0" encoding="UTF-8"?>
<configdata>
<nav>
	<home>
		<label>nav_home</label>
		<controller>index</controller>
		<pages>
			<add>
				<label>nav_fact_add</label>
				<controller>fact</controller>
				<action>add</action>
			</add>
			<list>
				<label>nav_fact_list</label>
				<controller>fact</controller>
			</list>
			<calc>
				<label>nav_calc</label>
				<controller>calc</controller>
			</calc>
			<user>
				<label>nav_user</label>
				<controller>user</controller>
			</user>
			<stats>
				<label>nav_sats</label>
				<controller>stats</controller>
			</stats>
		</pages>
	</home>
</nav>
</configdata>

Voilà, la balise a retenir est la balise pages qui permet de définir des sous pages ou sous menu. Et bien sur on peut en imbriquer autant qu’on veut.
Enfin il faut savoir que le code html des liens sur la page suit une hiérarchie de balise ul/li.

Classe css de la page en cours

Comment ajouter une classe au lien qui pointe vers la page en cours ? Et bien il suffit de rajouter ce bout de code en haut de chaque controller (dans la méthode init) :

	public function init()
	{
		/* Initialize action controller here */
		$activeNav = $this->view->navigation()->findByController('index');
		$activeNav->active = true;
		$activeNav->setClass("active");
	}

Et voilà maintenant quand on est sur une page du controller index (dans ce cas la) et bien le lien aura (entre autre) la classe active. Il suffit après de toucher au css pour ajouter un petit effet ;)

Vous en voulez encore plus ?

Fil de Navigation ou breadcrumbs

navigation-fil

Et bien avec Zend_Navigation on peut retracer notre chemin de navigation, qui soit dit en passant est très bon en terme d’ergonomie, mais aussi en terme de référencement. Donc je vous invite vraiment à le mettre en place. Encore une fois, il suffit de rajouter une ligne de php dans le fichier layout.phtml :

<?php echo $this->navigation()->breadcrumbs()->setMinDepth(0)->setLinkLast(true)->setSeparator(" >> "); ?>

Alors on décortique le bousin :

  • $this->navigation()->breadcrumbs() va afficher le fil de navigation.
  • ->setMinDepth(0) va définir si il faut ou pas afficher ce fil ; il est en accord direct avec la profondeur du xml.
  • ->setLinkLast(true) définit si il faut ou pas mettre un liens sur le dernier fils du fil de navigation qui correspond à la page en cours
  • ->setSeparator( » >> « ) définit par quelle chaine de caractère est séparer notre liste de liens.

Voilà, comme on a pu voir, le plus dur est de faire le fichier xml ainsi que le css des menus. Après c’est un jeux d’enfant pour avoir de beau menu ;)
[Header]

Articles en rapport :


Et on peut meme partager l'article:

  • Print
  • Twitter
  • Facebook
  • Digg
  • del.icio.us
  • Google Bookmarks
  • Netvibes
  • Blogosphere News
  • Identi.ca
  • LinkedIn
  • Technorati
  • Wikio FR
  • Yahoo! Buzz
  • Ping.fm

11 Commentaires

guitonoctobre 8th, 2009 at 22 h 49 min

sympa ton tuto, j’étais justement en plein dedans et ça résume bien le tout ! merci

Gregoctobre 11th, 2009 at 22 h 10 min

@guiton alors ce tutos t’as servit ?

jfragnovembre 23rd, 2009 at 18 h 46 min

Salut lyrixx

Bravo pour ton tuto clair et simple a mettre en place !!
Par contre j’ai une petite question je cherche a avoir un menu ou le premier niveau n’ai pas de controller / action !?

exemple :
°Menu //non cliquable
°Dessous //cliquable
°Dessous2 //cliquable

Sais-tu comment faut-il s’y prendre parce que lorsque je retire la balise controller il gueule !!

Gregnovembre 24th, 2009 at 1 h 18 min

Merci Beaucoup jfrag
Sinon pour ton problème et bien tu peux tout simplement mettre dans ton fichier xml un truc qui ressemble a ca :
< menu >
< label >Menu< /label >
< uri >< /uri>
< /menu>

En gros tu ne mets pas d’url dans la balise uri, et ca ne te fait pas de liens ;) , c’est aussi simple que ca !
ps : faut penser a virer les espaces dans les balises !

jfragnovembre 24th, 2009 at 10 h 38 min

merci beaucoup !

j’y ai pensé ce matin en allant au taf lol…

bonne continuation et merci pour ton blog qui m’a sauvé la vie plus d’une fois grace à t’es magnifique tuto ;)

Gregnovembre 24th, 2009 at 13 h 24 min

Encore merci, et n’hesites pas a faire de la pub ;)

Ferdikamjanvier 13th, 2010 at 19 h 49 min

l’attribut class= »active » pour le css est activé par défaut lorsqu’on utilise par exemple dans le fichier xml les balises mon_controllermon_action.
par contre quand on utilise les balises blabla à la place on utilise le script proposé plus haut.

Vincefévrier 18th, 2010 at 2 h 27 min

Ah merci!! enfin un tuto compréhensible !

FredTfévrier 18th, 2010 at 19 h 18 min

lu, merci de m’avoir mis sur la voie pour commencer,
pas tout compris ce que tu veux dire Ferdikam avec « l’attribut class » « activé par défaut » …
Sinon pour affecter la classe de style pour la rubrique en cours, la recherche de « index » m’a pas inspiré. Et si pas de résultat … Error :(

Pour un menu principal, J’ai fait cà:
$container=$this->navigation()->getContainer();
if ($active = $this->navigation()->findActive($container)) {
// La page active :
$active = $active['page'];
// recherche de la page Root de la page active
while ($parent = $active->getParent()) {
if ($parent === $container) {
break;
}
$active = $parent;
}
// affecte la classe de style pour la rubrique active
$active->setClass(« active »);
}

Ferdikamfévrier 18th, 2010 at 19 h 42 min

pour te répondre FredT

en fait dans le fichier xml, quand on utilise les balises
moncntroller
monaction

l’attribut class= »active » dans le code source est attribué à l’élément de la page en cours.

Par contre, quand on utilise la balise
monuri
à la place de celles citées plus haut
alors cet attribut n’apparaît pas

FredTfévrier 18th, 2010 at 20 h 16 min

Merci, j’ai compris, …
La classe active est bel et bien affecté aux automatiquement
Mais pas sur les .
setClass() attribut la classe juste aux

Laisser un commentaire

Votre commentaire :

Additional comments powered by BackType