1 <?xml version="1.0" encoding="UTF-8"?>
3 <sect1 id="zend.navigation.containers">
4 <title>Containers</title>
7 Containers have methods for adding, retrieving, deleting and
8 iterating pages. Containers implement the
9 <ulink url="http://php.net/spl">SPL</ulink> interfaces
10 <classname>RecursiveIterator</classname> and
11 <classname>Countable</classname>, meaning that a container can
12 be iterated using the SPL
13 <classname>RecursiveIteratorIterator</classname> class.
16 <sect2 id="zend.navigation.containers.creating">
17 <title>Creating containers</title>
20 <classname>Zend_Navigation_Container</classname> is
21 abstract, and can not be instantiated directly. Use
22 <classname>Zend_Navigation</classname> if you want to
23 instantiate a container.
27 <classname>Zend_Navigation</classname> can be constructed
28 entirely empty, or take an array or a
29 <classname>Zend_Config</classname> object with pages to put in the
30 container. Each page in the given array/config will eventually be
31 passed to the <methodname>addPage()</methodname> method of the container class,
32 which means that each element in the array/config can be an array or
33 a config object, or a <classname>Zend_Navigation_Page</classname>
37 <example id="zend.navigation.containers.creating.example.array">
38 <title>Creating a container using an array</title>
40 <programlisting language="php"><![CDATA[
42 * Create a container from an array
44 * Each element in the array will be passed to
45 * Zend_Navigation_Page::factory() when constructing.
47 $container = new Zend_Navigation(array(
55 'uri' => 'http://www.zend-project.com/',
60 'controller' => 'page2',
63 'label' => 'Page 2.1',
64 'action' => 'page2_1',
65 'controller' => 'page2',
66 'class' => 'special-one',
67 'title' => 'This element has a special class',
71 'label' => 'Page 2.2',
72 'action' => 'page2_2',
73 'controller' => 'page2',
74 'class' => 'special-two',
75 'title' => 'This element has a special class too'
80 'label' => 'Page 2 with params',
82 'controller' => 'page2',
83 // specify a param or two
90 'label' => 'Page 2 with params and a route',
92 'controller' => 'page2',
93 // specify a route name and a param for the route
94 'route' => 'nav-route-example',
102 'controller' => 'index',
103 'module' => 'mymodule',
104 'reset_params' => false
111 'label' => 'Page 4.1',
113 'title' => 'Page 4 using uri',
116 'label' => 'Page 4.1.1',
117 'title' => 'Page 4 using mvc params',
119 'controller' => 'page4',
120 // let's say this page is active
128 'label' => 'Page 0?',
129 'uri' => '/setting/the/order/option',
130 // setting order to -1 should make it appear first
136 // this page should not be visible
140 'label' => 'Page 5.1',
144 'label' => 'Page 5.1.1',
148 'label' => 'Page 5.1.2',
150 // let's say this page is active
160 'label' => 'ACL page 1 (guest)',
161 'uri' => '#acl-guest',
162 'resource' => 'nav-guest',
165 'label' => 'ACL page 1.1 (foo)',
167 'resource' => 'nav-foo'
170 'label' => 'ACL page 1.2 (bar)',
172 'resource' => 'nav-bar'
175 'label' => 'ACL page 1.3 (baz)',
177 'resource' => 'nav-baz'
180 'label' => 'ACL page 1.4 (bat)',
182 'resource' => 'nav-bat'
187 'label' => 'ACL page 2 (member)',
188 'uri' => '#acl-member',
189 'resource' => 'nav-member'
192 'label' => 'ACL page 3 (admin',
193 'uri' => '#acl-admin',
194 'resource' => 'nav-admin',
197 'label' => 'ACL page 3.1 (nothing)',
203 'label' => 'Zend Framework',
204 'route' => 'zf-route'
210 <example id="zend.navigation.containers.creating.example.config">
211 <title>Creating a container using a config object</title>
213 <programlisting language="php"><![CDATA[
214 /* CONTENTS OF /path/to/navigation.xml:
215 <?xml version="1.0" encoding="UTF-8"?>
221 <uri>http://www.zend-project.com/</uri>
226 <label>Page 1</label>
231 <label>Page 1.1</label>
232 <uri>page1/page1_1</uri>
239 <label>Page 2</label>
244 <label>Page 2.1</label>
245 <uri>page2/page2_1</uri>
249 <label>Page 2.2</label>
250 <uri>page2/page2_2</uri>
254 <label>Page 2.2.1</label>
255 <uri>page2/page2_2/page2_2_1</uri>
259 <label>Page 2.2.2</label>
260 <uri>page2/page2_2/page2_2_2</uri>
268 <label>Page 2.3</label>
269 <uri>page2/page2_3</uri>
273 <label>Page 2.3.1</label>
274 <uri>page2/page2_3/page2_3_1</uri>
278 <label>Page 2.3.2</label>
279 <uri>page2/page2_3/page2_3_2</uri>
284 <label>Page 2.3.2.1</label>
285 <uri>page2/page2_3/page2_3_2/1</uri>
290 <label>Page 2.3.2.2</label>
291 <uri>page2/page2_3/page2_3_2/2</uri>
296 <label>Ignore</label>
307 <label>Page 2.3.3</label>
308 <uri>page2/page2_3/page2_3_3</uri>
309 <resource>admin</resource>
313 <label>Page 2.3.3.1</label>
314 <uri>page2/page2_3/page2_3_3/1</uri>
319 <label>Page 2.3.3.2</label>
320 <uri>page2/page2_3/page2_3_3/2</uri>
321 <resource>guest</resource>
335 <label>Page 3</label>
340 <label>Page 3.1</label>
341 <uri>page3/page3_1</uri>
342 <resource>guest</resource>
346 <label>Page 3.2</label>
347 <uri>page3/page3_2</uri>
348 <resource>member</resource>
352 <label>Page 3.2.1</label>
353 <uri>page3/page3_2/page3_2_1</uri>
357 <label>Page 3.2.2</label>
358 <uri>page3/page3_2/page3_2_2</uri>
359 <resource>admin</resource>
366 <label>Page 3.3</label>
367 <uri>page3/page3_3</uri>
368 <resource>special</resource>
372 <label>Page 3.3.1</label>
373 <uri>page3/page3_3/page3_3_1</uri>
378 <label>Page 3.3.2</label>
379 <uri>page3/page3_3/page3_3_2</uri>
380 <resource>admin</resource>
392 <module>default</module>
393 <controller>index</controller>
394 <action>index</action>
401 $config = new Zend_Config_Xml('/path/to/navigation.xml', 'nav');
402 $container = new Zend_Navigation($config);
407 <sect2 id="zend.navigation.containers.adding">
408 <title>Adding pages</title>
411 Adding pages to a container can be done with the methods
412 <methodname>addPage()</methodname>, <methodname>addPages()</methodname>, or
413 <methodname>setPages()</methodname>. See examples below for explanation.
416 <example id="zend.navigation.containers.adding.example">
417 <title>Adding pages to a container</title>
419 <programlisting language="php"><![CDATA[
421 $container = new Zend_Navigation();
423 // add page by giving a page instance
424 $container->addPage(Zend_Navigation_Page::factory(array(
425 'uri' => 'http://www.example.com/'
428 // add page by giving an array
429 $container->addPage(array(
430 'uri' => 'http://www.example.com/'
433 // add page by giving a config object
434 $container->addPage(new Zend_Config(array(
435 'uri' => 'http://www.example.com/'
450 $container->addPages($pages);
452 // remove existing pages and add the given pages
453 $container->setPages($pages);
458 <sect2 id="zend.navigation.containers.removing">
459 <title>Removing pages</title>
462 Removing pages can be done with <methodname>removePage()</methodname> or
463 <methodname>removePages()</methodname>. The first method accepts a an instance
464 of a page, or an integer. The integer corresponds to the
465 <code>order</code> a page has. The latter method will remove all
466 pages in the container.
469 <example id="zend.navigation.containers.removing.example">
470 <title>Removing pages from a container</title>
472 <programlisting language="php"><![CDATA[
473 $container = new Zend_Navigation(array(
489 // remove page by implicit page order
490 $container->removePage(0); // removes Page 1
492 // remove page by instance
493 $page3 = $container->findOneByAction('Page 3');
494 $container->removePage($page3); // removes Page 3
496 // remove page by explicit page order
497 $container->removePage(200); // removes Page 2
500 $container->removePages(); // removes all pages
505 <sect2 id="zend.navigation.containers.finding">
506 <title>Finding pages</title>
509 Containers have finder methods for retrieving pages.
510 They are <methodname>findOneBy($property, $value)</methodname>,
511 <methodname>findAllBy($property, $value)</methodname>, and
512 <methodname>findBy($property, $value, $all = false)</methodname>.
513 Those methods will recursively search the container for
514 pages matching the given <code>$page->$property == $value</code>.
515 The first method, <methodname>findOneBy()</methodname>, will return a
516 single page matching the property with the given value, or
517 <constant>NULL</constant> if it cannot be found. The second method will return
518 all pages with a property matching the given value. The third
519 method will call one of the two former methods depending on the
520 <varname>$all</varname> flag.
524 The finder methods can also be used magically by appending the
525 property name to <code>findBy</code>, <code>findOneBy</code>, or
526 <code>findAllBy</code>, e.g. <methodname>findOneByLabel('Home')</methodname> to
527 return the first matching page with label <code>Home</code>.
528 Other combinations are <methodname>findByLabel(...)</methodname>,
529 <methodname>findOnyByTitle(...)</methodname>,
530 <methodname>findAllByController(...)</methodname>, etc. Finder
531 methods also work on custom properties, such as
532 <methodname>findByFoo('bar')</methodname>.
535 <example id="zend.navigation.containers.finding.example">
536 <title>Finding pages in a container</title>
538 <programlisting language="php"><![CDATA[
539 $container = new Zend_Navigation(array(
546 'label' => 'Page 1.1',
551 'label' => 'Page 1.2',
553 'class' => 'my-class',
557 'label' => 'Page 1.3',
565 'id' => 'page_2_and_3',
566 'class' => 'my-class',
568 'controller' => 'index',
573 'id' => 'page_2_and_3',
575 'controller' => 'index'
579 // The 'id' is not required to be unique, but be aware that
580 // having two pages with the same id will render the same id attribute
581 // in menus and breadcrumbs.
582 $found = $container->findBy('id',
583 'page_2_and_3'); // returns Page 2
584 $found = $container->findOneBy('id',
585 'page_2_and_3'); // returns Page 2
586 $found = $container->findBy('id',
588 true); // returns Page 2 and Page 3
589 $found = $container->findById('page_2_and_3'); // returns Page 2
590 $found = $container->findOneById('page_2_and_3'); // returns Page 2
591 $found = $container->findAllById('page_2_and_3'); // returns Page 2 and Page 3
593 // Find all matching CSS class my-class
594 $found = $container->findAllBy('class',
595 'my-class'); // returns Page 1.2 and Page 2
596 $found = $container->findAllByClass('my-class'); // returns Page 1.2 and Page 2
598 // Find first matching CSS class my-class
599 $found = $container->findOneByClass('my-class'); // returns Page 1.2
601 // Find all matching CSS class non-existant
602 $found = $container->findAllByClass('non-existant'); // returns array()
604 // Find first matching CSS class non-existant
605 $found = $container->findOneByClass('non-existant'); // returns null
607 // Find all pages with custom property 'foo' = 'bar'
608 $found = $container->findAllBy('foo', 'bar'); // returns Page 1 and Page 1.1
610 // To achieve the same magically, 'foo' must be in lowercase.
611 // This is because 'foo' is a custom property, and thus the
612 // property name is not normalized to 'Foo'
613 $found = $container->findAllByfoo('bar');
615 // Find all with controller = 'index'
616 $found = $container->findAllByController('index'); // returns Page 2 and Page 3
621 <sect2 id="zend.navigation.containers.iterating">
622 <title>Iterating containers</title>
625 <classname>Zend_Navigation_Container</classname> implements
626 <classname>RecursiveIteratorIterator</classname>, and can be
627 iterated using any <classname>Iterator</classname> class. To iterate
628 a container recursively, use the
629 <classname>RecursiveIteratorIterator</classname> class.
632 <example id="zend.navigation.containers.iterating.example">
633 <title>Iterating a container</title>
635 <programlisting language="php"><![CDATA[
637 * Create a container from an array
639 $container = new Zend_Navigation(array(
649 'label' => 'Page 2.1',
653 'label' => 'Page 2.2',
664 // Iterate flat using regular foreach:
665 // Output: Page 1, Page 2, Page 3
666 foreach ($container as $page) {
670 // Iterate recursively using RecursiveIteratorIterator
671 $it = new RecursiveIteratorIterator(
672 $container, RecursiveIteratorIterator::SELF_FIRST);
674 // Output: Page 1, Page 2, Page 2.1, Page 2.2, Page 3
675 foreach ($it as $page) {
682 <sect2 id="zend.navigation.containers.other">
683 <title>Other operations</title>
686 The method <methodname>hasPage(Zend_Navigation_Page $page)</methodname> checks
687 if the container has the given page. The method <methodname>hasPages()</methodname>
688 checks if there are any pages in the container, and is equivalent
689 to <code>count($container) > 1</code>.
693 The <methodname>toArray()</methodname> method converts the container and the
694 pages in it to an array. This can be useful for serializing and
698 <example id="zend.navigation.containers.other.example.toarray">
699 <title>Converting a container to an array</title>
701 <programlisting language="php"><![CDATA[
702 $container = new Zend_Navigation(array(
712 'label' => 'Page 2.1',
716 'label' => 'Page 2.2',
723 var_dump($container->toArray());
728 ["label"]=> string(6) "Page 1"
740 ["active"]=> bool(false)
741 ["visible"]=> bool(true)
742 ["type"]=> string(23) "Zend_Navigation_Page_Uri"
743 ["pages"]=> array(0) {
745 ["uri"]=> string(1) "#"
748 ["label"]=> string(6) "Page 2"
760 ["active"]=> bool(false)
761 ["visible"]=> bool(true)
762 ["type"]=> string(23) "Zend_Navigation_Page_Uri"
763 ["pages"]=> array(2) {
765 ["label"]=> string(8) "Page 2.1"
777 ["active"]=> bool(false)
778 ["visible"]=> bool(true)
779 ["type"]=> string(23) "Zend_Navigation_Page_Uri"
780 ["pages"]=> array(0) {
782 ["uri"]=> string(1) "#"
786 ["label"]=> string(8) "Page 2.2"
798 ["active"]=> bool(false)
799 ["visible"]=> bool(true)
800 ["type"]=> string(23) "Zend_Navigation_Page_Uri"
801 ["pages"]=> array(0) {
803 ["uri"]=> string(1) "#"
806 ["uri"]=> string(1) "#"