📜 ⬆️ ⬇️

Let's talk about Zend_Navigation

Exit 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, bread crumbs. Particular attention is paid to using 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).

First, create a project framework using Zend_Tool .
$ zf create project. /


1. Menu
To set up Zend_View, I add the following code to “application / configs / application.ini”:
; Views
resources.view.encoding = "UTF-8"
resources.view.basePath = APPLICATION_PATH "/ views"
resources.view.helperPath.Application_View_Helper = APPLICATION_PATH "/ views / helpers"
Further in the file “application / Bootstrap.php” I create a new method _initNavigation () (please read the comments in the code):
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
')
/ *
* Initialize the navigator object and pass it to the 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' => _ ( 'Home Page' ) ,
) ,
array (
'controller' => 'users' ,
'action' => 'index' ,
// I wrap the text in _ (), then to pull it out with a 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' => _ ( 'Authorization' ) ,
) ,
array (
'controller' => 'users' ,
'action' => 'logout' ,
'label' => _ ( 'Logout' ) ,
)
) ;

// Create a new container based on our structure
$ container = new Zend_Navigation ( $ pages ) ;
// Pass the container to the View
$ view -> menu = $ container ;

return $ container ;
}

}

If you follow a healthy logic, the menu should be present on all pages of the site (or most). Zend_Layout is perfect for this.
$ mkdir application / layouts
$ mkdir application / layouts / scripts
$ touch application / layouts / scripts / default.phtml
I add to the template “application / layouts / scripts / default.phtml” the output of the menu and page content:
<div id = "menu">
<h3>
<? php echo $ this -> translate ( 'Menu' ) ; ?> :
</ h3>

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

<div id = "content">
<? php echo $ this -> layout ( ) -> content ; ?>
</ div>

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 run (I wrote the original article in Ukrainian and screenshots to alter honestly speaking laziness :)):
:)
Voila :). We see the finished, slammed menu! The active item is marked as class = "active".

2. Bread Crumbs
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 the "bread crumbs".

So that the application does not swear at the lack of the desired controller or view, using Zend_Tool, I will create the Users controller 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 layout (between the menu and the content):
<div id = "breadcrumbs">
<h3>
<? php echo $ this -> translate ( 'Bread crumbs' ) ; ?> :
</ h3>
<? php echo $ this -> navigation ( ) -> breadcrumbs ( $ this -> menu ) -> setLinkLast ( true ) ; ?>
</ div>

Watch what happened:

Cool :)?
The setLinkLast (true) method means that the last crumb should be displayed as a link. You can also specify a separator and the minimum depth - see API

3. Sitemap
With sitemap is still as simple. Everything is done by analogy. Here is the manual , but the minimum code:
<? php echo $ this -> navigation ( ) -> sitemap ( $ this -> menu ) ; ?>


4. Zend_Navigation && Zend_Acl
And now I will talk about what I liked most about Zend_Navigation - the ability to use it in conjunction with Zend_Acl.
I add to Bootstrap the roles and privileges to access the pages, as well as the initialization of Zend_Acl (read the comments on the code!):
<? php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{

/ **
* Initialize the ACL.
* Create roles and resources. Distribute access rights
*
* @return Zend_Acl
* /
protected function _initAcl ( )
{
$ auth = Zend_Auth :: getInstance ( ) ;
// Define the user role.
// If not authorized - means "guest"
$ role = ( $ auth -> hasIdentity ( ) && ! empty ( $ auth -> getIdentity ( ) -> role ) )
? $ auth -> getIdentity ( ) -> role : 'guest' ;

$ acl = new Zend_Acl ( ) ;

// Create 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 for naming resources
// "mvc:" - for pages
$ acl -> add ( new Zend_Acl_Resource ( 'mvc: index' ) )
-> add ( new Zend_Acl_Resource ( 'mvc: error' ) )
-> add ( new Zend_Acl_Resource ( 'mvc: users' ) ) ;

// Let the guests on the "face" and on the error page
$ acl -> allow ( 'guest' , array ( 'mvc: error' , 'mvc: index' ) ) ;

// And also to the login and registration pages
$ acl -> allow ( 'guest' , 'mvc: users' , array ( 'login' , 'registration' ) ) ;
// And already the 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 ACLs to Zend_Navigation
Zend_View_Helper_Navigation_HelperAbstract :: setDefaultAcl ( $ acl ) ;
Zend_View_Helper_Navigation_HelperAbstract :: setDefaultRole ( $ role ) ;

return $ acl ;
}

/ *
* Initialize the navigator object and pass it to the View
*
* @return Zend_Navigation
* /
public function _initNavigation ( )
{
$ this -> bootstrapView ( ) ;
$ view = $ this -> getResource ( 'view' ) ;

$ pages = array (
array (
'controller' => 'index' ,
'label' => _ ( 'Home Page' ) ,
) ,
array (
'controller' => 'users' ,
'action' => 'index' ,
// Resource for checking access rights
'resource' => 'mvc: users' ,
// And privilege
'privilege' => 'index' ,
'label' => _ ( 'Users' ) ,
'pages' => array (
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' ) ,
) ,
array (
'controller' => 'users' ,
'action' => 'login' ,
'resource' => 'mvc: users' ,
'privilege' => 'login' ,
'label' => _ ( 'Authorization' ) ,
) ,
array (
'controller' => 'users' ,
'action' => 'logout' ,
'resource' => 'mvc: users' ,
'privilege' => 'logout' ,
'label' => _ ( 'Logout' ) ,
)
) ;

$ container = new Zend_Navigation ( $ pages ) ;
$ view -> menu = $ container ;

return $ container ;
}

}
?>

I run:

Well, I see the menu for guests. And there are no bread crumbs because you need to set the minimum depth to zero.

Results
In general, Zend_Navigation is a very convenient and flexible component. I also forgot to say that the standard view helpers support Zend_Translate, which is very convenient when creating multilingual sites.
It seems everything. I hope this article is useful to you. And come to our forum zendframework.ru (as well as on the site itself a lot of useful and interesting).

UPD. Here (or rather already there :)) san tells you what to do
$ view -> menu = $ container ;
not very convenient, because you can accidentally wipe 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 views like this:
<? php echo $ this -> navigation ( ) -> menu ( ) ; ?>
<? php echo $ this -> navigation ( ) -> breadcrumbs ( ) ; ?>


UPD2.
The hacker has jarool made a good point:
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 push and specify in the mailout when specifying the helper.

Source: https://habr.com/ru/post/64115/


All Articles