This tutorial covers a lot of the basic use cases with Zend_Navigation. Using a uri-based navigation.xml file, we generate a very simple menu system as well as a breadcrumb with some basic information. In the last 3 minutes I cover how to get a Google compliant sitemap from the navigation.xml file. This video is by no means exhaustive, but should get you up and running with Zend_Navigation in the Zend Framework.
Browse the code off google code or download a zip here.
On another note, I’m thinking of putting together a forum as a way of organizing some of the informative discussion I’ve found in the comments section. I know other forums exist so I’d be curious to know if you think zendcasts would benefit from such a thing.
Alternatively, if you have topics you’d like covered and are willing to step up to the mic, I’d love to share your own screencasts with the now over 550 subscribers!

Hi.
First off I congratulate you
for the site.
Excellent stuff
I’ve a problem with breacrumbs
with this
$this->navigation()->breadcrumbs()->setMinDepth(0)->setLinkLast(true)->setSeparator(” : “);
in the layout.phtml
I’ve got the first
breadcrumb when the request uri
is / or /guestbook but nothing when
the uri is /guestbook/sign for instance.
my navigation.xml
Home
index
index
Guestbook
guestbook
index
I’m new at zf so can you help me, please ?
Best regards.
Whisher
-configdata- -nav- -home- -label-Home-/label- -controller-index-/controller- -action-index-/action- -/home- -guestbook- -label-Guestbook-/label- -controller-guestbook-/controller- -action-index-/action- -/guestbook- -/nav- -/configdata-hi wisher,
in order for the breadcrumb to function correctly, you need to specify which page is active. You can do that manually by finding the node the Zend_Navigation container and then setting the $page->active = true;
for some reason, your signAction isn’t being setup to pickup the active element in the Zend_Navigation container. The reason I got it to work dynamically in the tutorial is because I used the preDispatch method and made sure to specify a tag for each page in my navigation.xml file.
hope that helps.
Jon
Hi jon.
whisher not wisher ^-^
Thanks for the quick reply.
I managed this code
class GuestbookController extends Zend_Controller_Action { public function indexAction() { $guestbook = new Default_Model_Guestbook(); $this->view->entries = $guestbook->fetchAll(); } public function signAction() { $activeNav = $this->view->navigation()->findByAction('index'); $activeNav->active = true; $activeNav->setClass("active-my"); } }the output is
li class=”active”
a class=”active-my”
but I don’t see any breadcrumbs yet
[The reason I got it to work dynamically in the tutorial is because I used the preDispatch method and made sure to specify a tag for each page in my navigation.xml file.]
Sorry may be I miss the point
but there isn’t any preDispatch
in the ControllerIndex.
An example would be gratefully appreciated
hey whisher (sorry for the misspelling),
I think you can write a function like this:
protected function setActiveNavigation()
{
$uri = $this->_request->getPathInfo();
$activeNav = $this->view->navigation()->findByUri($uri);
if ($activeNav == null)
$activeNav = $this->view->navigation()->findOneByController($this->_getParam(‘controller’));
if ($activeNav != null)
{
$activeNav->active = true;
$activeNav->setClass(“active”);
}
}
You should be able to call it either in preDispatch or in the actual action. I think its best to stick to one kind of format (either uri or controller / action) as a way of making the search tree easily traversed.
Hello Jon,
I just want to thank you for all your videos and in particular this one. It would have taken me some time to figure that one out.
Greetings
Marry
Very interesting! I didn’t use Zend_Nav yet, but I’m implementing it for sure in my next projects… looks very handy.
Jeroen
@Jon
Thanks
Thanks for all the tuts Jon it really helped me in getting started with Zend quickly.
Hi Jon,
I’ve created a menu with the help of your tutorial. The .xml I’m using is (Third try to display my xml):
[configdata]
[nav]
[home]
[label]Home[/label]
[controller]index[/controller]
[action]index[/action]
[pages]
[contact]
[label]Contact[/label]
[controller]contact[/controller]
[action]index[/action]
[/contact]
[reacties]
[label]Reacties[/label]
[controller]reacties[/controller]
[action]index[/action]
[/reacties]
[/pages]
[/home]
[/nav]
[/configdata]
The weird thing is that I cant’ navigate away from the About page anymore. Navigating to and from Home and Contact is fine. Navigating to the About page is also possible, but when on the About page, the links under the menu items are all to the About page itself.
Can you help me with this problem?
hey Jim,
that’s a good question… your navigation hierarchy looks fine here… If you’re talking about the “About” page specifically, then I think you’ll need to add it back into the navigation.xml file since its no longer there. Is the menu rendering at all?
Jon, thanks for the great videos. Are you planning to do one on auth/acl anytime soon?
I think, a forum would be a beneficial addition to your site.
@Jon,
I’ve figured it out. The problem was that the About page was using a router. I didn’t specify routes yet in the navigation file. Now I have specified [route]default[/route] for every page and it works.
Now I have another question. I’m using your setActiveNavigation() function and I’ve copied this function into every controller that is using it. Now I want to put this function in a helper class to avoid the copying everytime. I’ve created a helper class using the Zend_Framework_project features in Zend Studio for Eclipse so all naming should be fine. When I try to use the helperfunction, I get an errormessage that the function doesn’t exist and is not trapped in __call().
What is the the best thing to do?
Hey Jim,
Good question! I’ve found it really helpful to create a class (I usually call it BaseController) that inherits from Zend_Controller_Action.
I then define my preDispatch / init function there with any generalized functionality (i.e. security, general template configuration, default title pages, etc…)
Then I’ll have all my other Controllers extend the BaseController.
If I want to use preDispatch() or init() in those controllers, I simply need to call their parent:
public function preDispatch() {
parent::preDispatch()
// more code here
}
If you want to create functions that will be called in various Controllers across your site, just define them as protected / public in your BaseController. Hope that helps.
I have a requirement to build a breadcrumb that would maintain state.
Here is what I’m doing; I’m coding a flow in Zend 1.82 that is made up of the following pages A:Search–>B:List–>C:Detail. Once on the detail page I would like to have a breadcrumb that would display the following home>search>list; upon clicking either the search or list page I would like the user to be taken back to that page with context (i.e. the original data). Is there a way to do this with your current example or have you thought about a way someone might do this?
Cheers,
JLi
@Jon
Jon, I created a new controller called BaseController and extended it from Zend_Controller_Action. After that I used that class to extend my other controllers from this BaseController.
The weird thing is that I get an error message saying:
Fatal error: Class ‘BaseController’ not found in /../application/controllers/IndexController.php on line 3
line 3 is the class header:
class IndexController extends BaseController
BaseController is in the same folder as the other controllers. What could be the problem?
and you’re certain that its called BaseController.php?
You could also put a require_once statement at the beginning of the IndexController… but you shouldn’t have too… I would double check the include paths.
Great Video! Congratulations! Can u explain how to use Zend_Navigation with ACL Rules? I need use Navigation on a system that requires some user levels, so I can’t show all options on menu for all users.
Thank you for putting this together!
Hi Diego,
I’m working on Zend ACL for my next video, however I try and keep the components separated unless its absolutely necessary so that they can be explored in their own context. I would probably use the two together by extending the Zend Menu View Helper and overriding the htmlify method by introducing some sort of check from Zend_ACL.
The most common mistake of them all:
You are not specifying the content-type !!
$this->_respons->setHeader(‘Content-Type’,'text/xml;charset=utf-8′);
One can’t stress enough how important this.
The HTTP protocol REQUIRES you to ALWAYS give correct Content-Types. The reason why the sitemap looked wierd in Firefox was cuz you did not give a correct content-type header.
And ohh, google can some times ignore your sitemap if its not identified with the correct headers.
I am not able to navigate on my Windows development system like shown in the Video.
I can see the index page – so far the script is working fine.
But this “/index/about” thing gives me always a 404 !
I changed httpd.conf a lot tweaking with aliases and virtual-hosts – I tested it with ZendServerCE and VertigoServ (another application stack like WAMP or MAMP) without finding a solution…
Best reguards
Frank
Jon,
I’m having problems with my navigation menu. I’ve used your tutorial and now I’ve added a module to my application and I’m not sure how to structure this in my navigation.xml file.
Is there good documentation somewhere about the structure of the navigation.xml?
The problem is that the toplevel pages (default module) are displayes correctly in the menu, but when I click on the menu item that is in the seperate module, the menu dissapears. What I want in the menu are the toplevel default menuitems and also the current module’s page with it’s subpages.
Could you help me with this?
I would double check your .htaccess file and make sure that WAMP has mod_rewrite enabled. I just posted a video by Tawfek about how to setup WAMP… it might help you in this case. Also, make sure that you have a front controller specified in you application.ini. If all else fails, I would suggest grabbing the project off of google code and working backwards. Hope that helps,
-
j
Zend_Navigation used to be part of the Zym framework: http://www.zym-project.com/docs/reference/zym.navigation.html so there might be a little more information there. In terms of default menu items and modules, you might have to have both modules run a plugin beforehand, or have them inherit from a Base Controller that will setup Zend_Navigation for you.
Do you know some documentation about the syntax/structure/nodes of the navigation.xml?
I guess it has something to do with my xml file.
Same Problem even with SVN code checkout under Windows running ZendServer-ce meanwhile
Hello,
I figured out where the mistake was.
It was misconfiguration of the directory directive in httpd.conf.
AllowOverride All
Best reguards
Frank
Hi Jon!
Cool screencast. It is very good introduction in Zend_Navigation.
P.S. Your previoust tutorial was about Zend_Tool. So why don’t you use it when creating actions?
zf create action contact index 1
zf create action about index 1
zf create action sitemap index 0.
I think it would be useful to teach people to use this stuff.
I see a couple of people requesting the XML config syntax. As the author of the component, I should be able to clarify on this.
Zend_Navigation maps pairs from the config (that is generated from the XML file) to setter methods. If you have a Home under a page in your XML, the page object will first look for a method called setLabel(), and call that with the given value. If the method doesn’t exist, the ‘label’ => ‘Home’ pair is stored as a custom property in the page, which you may access as any other native property. Same goes for a page’s sub pages; … will map to setPages() etc.
The page factory determines which type of page to create (URI, MVC, custom), so the XML syntax depends on the type of page you’re creating.
If you’re creating a URI page, you’ll have the common page options available, plus the ‘uri’ option. All options are listed in tables in the manual:
Common page options:
http://framework.zend.com/manual/en/zend.navigation.pages.html#zend.navigation.pages.common.options
URI page options (well, just one, really):
http://framework.zend.com/manual/en/zend.navigation.pages.html#zend.navigation.pages.uri.options
MVC page options:
http://framework.zend.com/manual/en/zend.navigation.pages.html#zend.navigation.pages.mvc.options
There should be several examples around the manual, showing how to use various properties, including those specified as arrays in the manual.
Hope this helps,
http://twitter.com/robinsk
I see a couple of people requesting the XML config syntax. As the author of the component, I should be able to clarify on this.
Zend_Navigation maps <name, value) pairs from the config (that is generated from the XML file) to setter methods. If you have a <label>Home</label> under a page in your XML, the page object will first look for a method called setLabel(), and call that with the given value. If the method doesn’t exist, the ‘label’ => ‘Home’ pair is stored as a custom property in the page, which you may access as any other native property. Same goes for a page’s sub pages; <pages>…</pages> will map to setPages() etc.
The page factory determines which type of page to create (URI, MVC, custom), so the XML syntax depends on the type of page you’re creating.
If you’re creating a URI page, you’ll have the common page options available, plus the ‘uri’ option. All options are listed in tables in the manual:
Common page options:
http://framework.zend.com/manual/en/zend.navigation.pages.html#zend.navigation.pages.common.options
URI page options (well, just one, really):
http://framework.zend.com/manual/en/zend.navigation.pages.html#zend.navigation.pages.uri.options
MVC page options:
http://framework.zend.com/manual/en/zend.navigation.pages.html#zend.navigation.pages.mvc.options
There should be several examples around the manual, showing how to use various properties, including those specified as arrays in the manual.
Hope this helps,
http://twitter.com/robinsk
I tried combining the Zend_Navigation example with Zend DB Update and Delete.
The problem is when pages are called that have parameters, e.g. http://localhost/index/update/1 it fails with:
Fatal error: Call to undefined method stdClass::setClass() in /usr/local/Zend/apache2/htdocs/quickstart/application/controllers/IndexController.php on line 122
I worked around this problem by checking for:
if ($activeNav != null) { } and this avoids the error but now no breadcrumbs are printed at all for these pages.
I think the solution would be to isolate the action but I don’t know how to do this.
I tried Jim’s method of [route]default[/route] but I think this might be off track.
What I also find curious is that wrapping a try – catch block around $activeNav->setClass ( “active” ); does catch the exception. There is still a lot I don’t understand about Zend Framework.
Great video…
But I’m a bit stuck with the css now. My Bootstrap class used to say:
$view->headLink()->appendStylesheet(‘/css/mystyle.css’);
but because of the nav, the pages under home (e.g. About at /index/about and Contact at /index/contact) now can’t find their css stylesheets anymore. And my images.
How do I dynammically append my Stylesheets to this new nav?
hey Isolde,
if you’re looking to have dynamically added stylesheets, you can do it in the controller as well, either in the action() methods or in preDispatch().
e.g. $this->view->headLink()->appendStylesheet(’/css/mystyle.css’);
You could write some code to inspect which controller / action you’re currently in and load the css dynamically, either through a plugin or by inheriting from another Controller (e.g. a BaseController that extends Zend_Controller_Action) that has shared functionality across multiple Controllers.
Thanks Jon, for the quick reply. I’ve solved it in the preDispatch (thanks again) for now but I like the idea of a BaseController. I’m going to try that.
hi ,
i get this error :
Uncaught exception ‘Zend_Navigation_Exception’ with message ‘Invalid argument: Unable to determine class to instantiate’..
any ideas ?
thanx
to answer to myself :
check not to have more nodes with the same name in the xml file
I’m getting the same error as Dan, but not the same cause.
My navigation.xml is identical to the demo.
And now I’m subscribing because I didn’t see the checkbox under the submit button (weird place for a checkbox)
Scrap all that. I had the tag before the pages. Awesome error reporting.
Sorry. The home closing tag.
Hi, I’ve been watching your screencasts and they are very usefull. Now I’m creating my breadcrumbs and I’m using the same technique as Jon.
I created a BaseController that contains the setActiveNavigation function. Now, when I extend my BaseController I get an error that the BaseController can’t be found. I don’t know how Jon fixed it, maybe you do? It works fine if I use include_once.
This is the code i use to set my include path:
set_include_path(implode(PATH_SEPARATOR, array(
realpath(APPLICATION_PATH . ‘/../library’),
get_include_path(),
)));
I hope you can help me out
.
If you use the mvc instead of uri, you dont have to go through the hassle of finding the active menu; the object will do it for you!
Luis,
you’re quite right, however this is an excellent example of where practice and theory are divergent. I would venture to guess that most non-trivial web application will have components that are divergent from the typical MVC page-to-navigation model. Relying on mvc instead of uri will work until your client asks for optimized SEO urls or when you need to migrate legacy pages. I think its important to know how to manually set active pages, if nothing more than being able to change the breadcrumb due to Authorization or user constraints.
Well, after a hell of tryings with this error:
Invalid argument: Unable to determine class to instantiate… finally I got the solution…
THE XML MUST BE CORRECT: Look you home tag, the pages is inside!!!!.
Great Tutorial!!!!… thanks a lot.
Acl.
Very helpful tutorial ! Zend Navigation will make my programmer’s life a little easier : )
Hi Jon,
This is a very helpful tutorial! How do you assign an ACL to this menu so that the menu changes accordingly to the permissions associated with the user? My current solution is a fixed menu once user logs in which is not that efficient. Here’s the scenario:
User goes to website as:
1. Guest Account:
Home
– About
2. Member Account:
Home
– Member
+ Profile
– About
3. Admin Account:
– Admin
+ Manage Users
– About
Something like that? Thanks!
Hey, i’m really affraid about this Videotutorials …
It’s an awesome ressource on the Web … Keep up the good work …
Greetz from germany …
very helpful tuts! keep on shinning! thanks!
Hi all,
Here’s the resource added to nav xml:
User
/user
free_account_section
Got the thing working by placing the navigation object in acl:
$this->_view->navigation()->setAcl($acl)
->setRole($getRank());
where $user is a class having this:
public function getRank() {
if ($auth->hasIdentity()) return Roles::FREE;
return Roles::GUEST;
}
Regards,
Burn