Talk about Zend_Navigation
The release of ZF 1.8 pleased us with several new (and most importantly very useful) components. In this article I want to talk about the practice of using Zend_Navigation to build a site menu, site map, breadcrumbs. I will pay special attention to the use of Zend_Navigation in conjunction with Zend_Acl.
This is a translation of an article from my blog. Since it is published on several sites, the most complete version will always be the original (in Ukrainian).
To get started, let's create a project wireframe using Zend_Tool .
1. Menu
To configure Zend_View, I add the following code to “application / configs / application.ini”:
If you follow a healthy logic, then the menu should be present on all pages of the site (or most). Zend_Layout is perfect for this.
This is a translation of an article from my blog. Since it is published on several sites, the most complete version will always be the original (in Ukrainian).
To get started, let's create a project wireframe using Zend_Tool .
$ zf create project ./
1. Menu
To configure Zend_View, I add the following code to “application / configs / application.ini”:
; ViewsFurther in the file “application / Bootstrap.php” I create a new method _initNavigation () (please read the comments in the code):
resources.view.encoding = "UTF-8"
resources.view.basePath = APPLICATION_PATH "/ views"
resources.view.helperPath.Application_View_Helper = APPLICATION_PATH "/ views / helpers"
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
/ *
* Initialize the navigator object and pass it to View
*
* @return Zend_Navigation
* /
public function _initNavigation ()
{
// Bootstrap View
$ this-> bootstrapView ();
$ view = $ this-> getResource ('view');
// Simple menu structure (can be rendered in XML)
$ pages = array (
array (
'controller' => 'index',
'label' => _ ('Main page'),
),
array (
'
'action' => 'index',
// I wrap the text in _ () so that I can then extend it with the gettext parser
'label' => _ ('Users'),
' pages' => array (
array (
'controller '=>' users',
'action' => 'new',
'label' => _ ('Add user'),
),
)
),
array (
'controller' => 'users',
' action '=> 'registration',
'label' => _ ('Registration'),
),
array (
'controller' => 'users',
'action' => 'login',
'label' => _ ('Login'),
),
array (
'controller' => 'users',
'action' => 'logout',
'label' => _ ('Exit'),
)
);
// Create a new container based on our structure
$ container = new Zend_Navigation ($ pages);
// Pass the container to View
$ view-> menu = $ container;
return $ container;
}
}
If you follow a healthy logic, then the menu should be present on all pages of the site (or most). Zend_Layout is perfect for this.
$ mkdir application / layoutsAdd the menu and page content output to the "application / layouts / scripts / default.phtml" template:
$ mkdir application / layouts / scripts
$ touch application / layouts / scripts / default.phtml
translate ('Menu'); ?>:
navigation () -> menu ($ this-> menu); ?>
layout () -> content; ?>
And in "application / configs / application.ini" I make settings for the layout resource, which initializes Zend_Layout:
; Layout
resources.layout.layout = "default"
resources.layout.layoutPath = APPLICATION_PATH "/ layouts / scripts"
And I’m launching (I wrote the original article in Ukrainian and redo the screenshots honestly too lazy :)): Voila :). We see the finished, popped menu! The active item is marked as class = "active". 2. Breadcrumbs Ok, the menu is ready. Now I want the user to always see his current location when using the site. To do this, you can use "bread crumbs". So that the application does not swear at the lack of the necessary controller or views, I will create the Users controller using Zend_Tool and add the necessary actions to it. Everything is very simple:

$ zf create controller users
$ zf create action new --controller-name users
$ zf create action registration --controller-name users
$ zf create action login --controller-name users
$ zf create action logout --controller-name users
Well, I’ll add some new code to the layout'a template (between the menu and the content):
translate ('Breadcrumbs'); ?>:
navigation () -> breadcrumbs ($ this-> menu) -> setLinkLast (true); ?>
Look what happened: Cool :)? The setLinkLast (true) method means that the last crumb needs to be displayed as a link. You can also specify the separator and the minimum depth - see API 3. Sitemap With the sitemap, everything is just as simple. Everything is done by analogy. Here is the manual , and here is the minimum code:

navigation () -> sitemap ($ this-> menu); ?>
4. Zend_Navigation && Zend_Acl
And now I’ll talk about what I liked most about Zend_Navigation - the ability to use it in conjunction with Zend_Acl.
I add roles and privileges to Bootstrap to access pages, as well as initialization of Zend_Acl (read the comments on the code!):
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
/ **
* Initialize the ACL.
* Create roles and resources. We give access rights
*
* @return Zend_Acl
* /
protected function _initAcl ()
{
$ auth = Zend_Auth :: getInstance ();
// Define the user role.
// If not authorized, then means "guest"
$ role = ($ auth-> hasIdentity () &&! Empty ($ auth-> getIdentity () -> role))
? $ auth-> getIdentity () -> role: 'guest';
$ acl = new Zend_Acl ();
// Create the roles
$ acl-> addRole (new Zend_Acl_Role ('guest'))
-> addRole (new Zend_Acl_Role ('member'), 'guest')
-> addRole (new Zend_Acl_Role ('administrator'), 'member');
// Create resources
// I use prefixes to name the resources
// "mvc:" - for the pages
$ acl-> add (new Zend_Acl_Resource ('mvc: index'))
-> add (new Zend_Acl_Resource ('mvc: error') )
-> add (new Zend_Acl_Resource ('mvc: users'));
// Put guests on the "face" and on the error page
$ acl-> allow ('guest', array ('mvc: error', 'mvc: index'));
// And also on the login and registration pages
$ acl->
// And the members are already a bummer :)
$ acl-> deny ('member', 'mvc: users', array ('login', 'registration'));
// Well, etc.
$ acl-> allow ('member', 'mvc: users', array ('index', 'logout'));
$ acl-> allow ('administrator', 'mvc: users', array ('new'));
// Cling the ACL to Zend_Navigation
Zend_View_Helper_Navigation_HelperAbstract :: setDefaultAcl ($ acl);
Zend_View_Helper_Navigation_HelperAbstract :: setDefaultRole ($ role);
return $ acl;
{
$ this-> bootstrapView ();
$ view = $ this-> getResource ('view');
$ pages = array (
array (
'controller' => 'index',
'label' => _ ('Home'),
),
array (
'controller' => 'users',
'action' => 'index' ,
// Resource for checking access rights
'resource' => 'mvc: users',
// And the privilege
'privilege' => 'index',
'label'
array (
'controller' => 'users',
' action '=>' new ',
' resource '=>' mvc: users',
'privilege' => 'new',
'label' => _ ('Add user '),
),
)
),
array (
' controller '=>' users ',
' action '=>' registration ',
' resource '=>' mvc: users ',
'privilege '=>' registration ',
' label '=> _ (' Registration '),
),
) ); $ container = new Zend_Navigation ($ pages); $ view-> menu = $ container;
return $ container;
}
}
?>
Launch: Well, I see a menu for guests. But there is no breadcrumbs because you need to set the minimum depth to zero. Summary In general, Zend_Navigation is a very convenient and flexible component. I also forgot to say that standard view helpers support Zend_Translate, which is very convenient when creating multilingual sites. Everything seems to be. I hope this article comes in handy. And come to our forum zendframework.ru (as well as on the site itself a lot of useful and interesting). UPD Here (more precisely already there :)) san suggests that you do this

$ view-> menu = $ container;not very convenient, because you can accidentally overwrite this variable in the controller.
If the site has only one menu, then you can do it easier:
$ view-> navigation ($ container);
And display it in the views this way:
navigation () -> menu (); ?>
navigation () -> breadcrumbs (); ?>
UPD2.
The jarool user made a sensible remark:
For most applications, one navigation object and one ACL are built. Therefore, you can put the menu in Zend_Registry :: set ('Zend_Navigation', $ AppNavigation) - the helpers themselves will find and do not need to shove and indicate in the layout when calling the helper.