Navigation Demo

Zym_Navigation is a component for managing a hierarchical structure of (logical representations of) web pages. It can be used for creating menus, breadcrumbs and sitemaps, and may be iterated and traversed in your very own way.

In this page:

Creating a navigation structure

When creating a navigation structure, there are a two types of pages supported, and a number of options available. The two types are:

  1. Zym_Navigation_Page_Mvc
  2. Zym_Navigation_Page_Uri

The first is meant for "internal" pages, and is defined using MVC parameters like module, controller, action, params, and route name. The second type can also be used for internal pages, but is generally considered to be off-site, e.g. if you want to link to another domain, or have some other logic to it.

Below are the available options for the two page types.

Table 1: Page options
Property Description MVC URI
label A label for the page. This will be used in the view helpers described below. R R
uri Specifies the page's URI. R
action Specifies the page's action. R
controller Specifies the page's controller. R
module Specifies the page's module. Defaults to default. O
route Specifies a route name to use when assembling URLs. Defaults to default. O
params An associative array of params to use when assembling the URL. Defaults to none. O
reset_params Whether the current request's params should be reset when assembling the URL. Defaults to true. O
title A more descriptive title that can be used to provide some description for a page. If set, this property will be used in Zym_View_Helper_Menu. O O
active Whether the page should be considered active for the current request. If active is false or not given, MVC pages will check its properties against the request object upon calling $page->isActive(). O O
visible Whether the page should be considered visible for the current request. Invisible pages are skipped by the view helpers below. O O
id An id tag/attribute that may be used for the page, typically in an anchor element. O O
class A CSS class that may be used for the page, typically in an anchor element. O O
target Specifies a target that may be used for the page, typically in an anchor element. O O
position Works like order for elements in Zend_Form. If specified, the page will be iterated in a specific order, meaning you can force a page to be iterated first by setting position to something like -100. O O
R = required, O = optional, – = not available

Any other (unrecognized) properties will be stored in the page as custom properties. Such properties can be retrieved and set using the magic overloads, e.g. $page->foo = 'bar';. Examples of custom properties that are used can be found in the view helper Zym_View_Helper_Sitemap, namely lastmod, changefreq, and priority.

So, with that in mind, let's create an example site structure:

<?php
/*
 * An array of example pages
 * 
 * Each element in the array will be passed to
 * Zym_Navigation_Page::factory() when constructing
 * the navigation object below.
 */
$config = array(
    array(
        
'label' => 'Page 1',
        
'action' => 'index',
        
'controller' => 'index',
        
'id' => 'home-link'
    
),
    array(
        
'label' => 'Zym',
        
'uri' => 'http://www.zym-project.com/',
        
'position' => 100
    
),
    array(
        
'label' => 'Page 2',
        
'action' => 'index',
        
'controller' => 'page2',
        
'pages' => array(
            array(
                
'label' => 'Page 2.1',
                
'action' => 'page2_1',
                
'controller' => 'page2',
                
'class' => 'special-one',
                
'title' => 'This element has a special class',
                
'active' => true
            
),
            array(
                
'label' => 'Page 2.2',
                
'action' => 'page2_2',
                
'controller' => 'page2',
                
'class' => 'special-two',
                
'title' => 'This element has a special class too'
            
)
        )
    ),
    array(
        
'label' => 'Page 2 with params',
        
'action' => 'index',
        
'controller' => 'page2',
        
// specify a param or two
        
'params' => array(
            
'format' => 'json',
            
'foo' => 'bar'
        
)
    ),
    array(
        
'label' => 'Page 2 with params and a route',
        
'action' => 'index',
        
'controller' => 'page2',
        
// specify a route name and a param for the route
        
'route' => 'nav-route-example',
        
'params' => array(
            
'format' => 'json'
        
)
    ),
    array(
        
'label' => 'Page 3',
        
'action' => 'index',
        
'controller' => 'index',
        
'module' => 'mymodule',
        
'reset_params' => false
    
),
    array(
        
'label' => 'Page 4',
        
'uri' => '#',
        
'pages' => array(
            array(
                
'label' => 'Page 4.1',
                
'uri' => '/page4',
                
'title' => 'Page 4 using uri',
                
'pages' => array(
                    array(
                        
'label' => 'Page 4.1.1',
                        
'title' => 'Page 4 using mvc params',
                        
'action' => 'index',
                        
'controller' => 'page4',
                        
// let's say this page is active
                        
'active' => '1'
                    
)
                )
            )
        )
    ),
    array(
        
'label' => 'Page 0?',
        
'uri' => '/setting/the/position/option',
        
// setting position to -1 should make it appear first
        
'position' => -1
    
),
    array(
        
'label' => 'Page 5',
        
'uri' => '/',
        
// this page should not be visible
        
'visible' => false,
        
'pages' => array(
            array(
                
'label' => 'Page 5.1',
                
'uri' => '#',
                
'pages' => array(
                    array(
                        
'label' => 'Page 5.1.1',
                        
'uri' => '#',
                        
'pages' => array(
                            array(
                                
'label' => 'Page 5.1.2',
                                
'uri' => '#',
                                
// let's say this page is active
                                
'active' => true
                            
)
                        )
                    )
                )
            )
        )
    ),
    array(
        
'label' => 'ACL page 1 (guest)',
        
'uri' => '#acl-guest',
        
'role' => 'nav-guest',
        
'pages' => array(
            array(
                
'label' => 'ACL page 1.1 (foo)',
                
'uri' => '#acl-foo',
                
'role' => 'nav-foo'
            
),
            array(
                
'label' => 'ACL page 1.2 (bar)',
                
'uri' => '#acl-bar',
                
'role' => 'nav-bar'
            
),
            array(
                
'label' => 'ACL page 1.3 (baz)',
                
'uri' => '#acl-baz',
                
'role' => 'nav-baz'
            
),
            array(
                
'label' => 'ACL page 1.4 (bat)',
                
'uri' => '#acl-bat',
                
'role' => 'nav-bat'
            
)
        )
    ),
    array(
        
'label' => 'ACL page 2 (member)',
        
'uri' => '#acl-member',
        
'role' => 'nav-member'
    
),
    array(
        
'label' => 'ACL page 3 (admin',
        
'uri' => '#acl-admin',
        
'role' => 'nav-admin',
        
'pages' => array(
            array(
                
'label' => 'ACL page 3.1 (nothing)',
                
'uri' => '#acl-nada'
            
)
        )
    ),
    array(
        
'label' => 'Zend Framework',
        
'route' => 'zf-route'
    
)
);

// Create navigation from array
$navigation = new Zym_Navigation($config);

// put navigation in registry so it's found by helpers
Zend_Registry::set('Zym_Navigation'$navigation);

// add a route to show that zym_navigation
// can be aware of routes and params
$front Zend_Controller_Front::getInstance();
$router $front->getRouter();
$router->addRoute(
    
'nav-route-example',
    new 
Zend_Controller_Router_Route('page2/:format', array(
        
'controller' => 'page2''action' => 'index')
    )
);
$router->addRoute(
    
'zf-route',
    new 
Zend_Controller_Router_Route(array(
        
'host' => 'framework.zend.com',
        
'path' => '/')
    )
);

// add some ACL stuff
$navAcl = new Zend_Acl();
$navAcl->addRole(new Zend_Acl_Role('nav-guest'));
$navAcl->addRole(new Zend_Acl_Role('nav-member'), 'nav-guest');
$navAcl->addRole(new Zend_Acl_Role('nav-admin'), 'nav-member');
$navAcl->addRole(new Zend_Acl_Role('nav-foo'));
$navAcl->addRole(new Zend_Acl_Role('nav-bar'));
$navAcl->addRole(new Zend_Acl_Role('nav-baz'));
$navAcl->addRole(new Zend_Acl_Role('nav-bat'));
Zend_Registry::set('Zym_Navigation_Acl'$navAcl);

// do the following in the view (for this demo we keep it simple)
/*
$this->menu()->setAcl(Zend_Registry::get('Zym_Navigation_Acl'));
$this->menu()->setRole(array('nav-member', 'nav-bar'));
*/

The navigation instance is now in the registry, and is found automatically by the view helpers below because of the key Zym_Navigation. The navigation structure may also be created using Zym_App_Resource_Navigation, in which case it will be set up from a config, and put it in the registry.

Zym_View_Helper_Menu

A menu can be printed using the view helper Zym_View_Helper_Menu. To print the menu using 4 initial spaces of indentation, simply do <?= $this->menu()->toString(4); ?>, or just <?= $this->menu(); ?> without indentation. The output will be:

This look and feel can easily be configured with CSS.

Zym_View_Helper_Breadcrumbs

Breadcrumbs are used to indicate where you are in the sitemap. To print breadcrumbs, all you have to do is: <?= $this->breadcrumbs(); ?>. This will print breadcrumbs from the deepest active page and upwards to the root, which in the structure above will be:

Page 4 > Page 4.1 > Page 4.1.1

Customize it by specifying some options, and print it again: <?php
$this
->breadcrumbs()->setLinkLast(true);
$this->breadcrumbs()->setSeparator('<span class="separator"> &#9654; </span>');
echo 
$this->breadcrumbs();

Page 4Page 4.1Page 4.1.1

Zym_View_Helper_Sitemap

This view helper prints a navigation structure as an XML sitemap, as defined here: http://www.sitemaps.org/protocol.php. To print the XML, all you do is <?= $this->sitemap(); ?>. The sitemap can be validated using Zym's sitemap validators and/or using schema validation. Several options are available, such as turning off XML declaration, setting maximum depth to print sitemap for, and whether output should be pretty-formatted.

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>http://demo.zym-project.com/setting/the/position/option</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/page2</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/page2/page2_1</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/page2/page2_2</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/page2/index/format/json/foo/bar</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/page2/json</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/mymodule</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/demo/navigation/#</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/page4</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/page4</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/demo/navigation/#acl-guest</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/demo/navigation/#acl-foo</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/demo/navigation/#acl-bar</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/demo/navigation/#acl-baz</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/demo/navigation/#acl-bat</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/demo/navigation/#acl-member</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/demo/navigation/#acl-admin</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/demo/navigation/#acl-nada</loc>
  </url>
  <url>
    <loc>http://demo.zym-project.com/Array</loc>
  </url>
  <url>
    <loc>http://www.zym-project.com/</loc>
  </url>
</urlset>

This demo app has implemented the sitemap.xml via Default_SitemapController and a route which you can visit here: /sitemap.xml