[MANUAL] English:
[zend.git] / documentation / manual / en / module_specs / Zend_Navigation-Containers.xml
blob6ce1eea5af43c970c85917a9eeec77ee76c3f40d
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Reviewed: no -->
3 <sect1 id="zend.navigation.containers">
4     <title>Containers</title>
6     <para>
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.
14     </para>
16     <sect2 id="zend.navigation.containers.creating">
17         <title>Creating containers</title>
19         <para>
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.
24         </para>
26         <para>
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>
34             instance.
35         </para>
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
43  *
44  * Each element in the array will be passed to
45  * Zend_Navigation_Page::factory() when constructing.
46  */
47 $container = new Zend_Navigation(array(
48     array(
49         'label' => 'Page 1',
50         'id' => 'home-link',
51         'uri' => '/'
52     ),
53     array(
54         'label' => 'Zend',
55         'uri' => 'http://www.zend-project.com/',
56         'order' => 100
57     ),
58     array(
59         'label' => 'Page 2',
60         'controller' => 'page2',
61         'pages' => array(
62             array(
63                 'label' => 'Page 2.1',
64                 'action' => 'page2_1',
65                 'controller' => 'page2',
66                 'class' => 'special-one',
67                 'title' => 'This element has a special class',
68                 'active' => true
69             ),
70             array(
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'
76             )
77         )
78     ),
79     array(
80         'label' => 'Page 2 with params',
81         'action' => 'index',
82         'controller' => 'page2',
83         // specify a param or two
84         'params' => array(
85             'format' => 'json',
86             'foo' => 'bar'
87         )
88     ),
89     array(
90         'label' => 'Page 2 with params and a route',
91         'action' => 'index',
92         'controller' => 'page2',
93         // specify a route name and a param for the route
94         'route' => 'nav-route-example',
95         'params' => array(
96             'format' => 'json'
97         )
98     ),
99     array(
100         'label' => 'Page 3',
101         'action' => 'index',
102         'controller' => 'index',
103         'module' => 'mymodule',
104         'reset_params' => false
105     ),
106     array(
107         'label' => 'Page 4',
108         'uri' => '#',
109         'pages' => array(
110             array(
111                 'label' => 'Page 4.1',
112                 'uri' => '/page4',
113                 'title' => 'Page 4 using uri',
114                 'pages' => array(
115                     array(
116                         'label' => 'Page 4.1.1',
117                         'title' => 'Page 4 using mvc params',
118                         'action' => 'index',
119                         'controller' => 'page4',
120                         // let's say this page is active
121                         'active' => '1'
122                     )
123                 )
124             )
125         )
126     ),
127     array(
128         'label' => 'Page 0?',
129         'uri' => '/setting/the/order/option',
130         // setting order to -1 should make it appear first
131         'order' => -1
132     ),
133     array(
134         'label' => 'Page 5',
135         'uri' => '/',
136         // this page should not be visible
137         'visible' => false,
138         'pages' => array(
139             array(
140                 'label' => 'Page 5.1',
141                 'uri' => '#',
142                 'pages' => array(
143                     array(
144                         'label' => 'Page 5.1.1',
145                         'uri' => '#',
146                         'pages' => array(
147                             array(
148                                 'label' => 'Page 5.1.2',
149                                 'uri' => '#',
150                                 // let's say this page is active
151                                 'active' => true
152                             )
153                         )
154                     )
155                 )
156             )
157         )
158     ),
159     array(
160         'label' => 'ACL page 1 (guest)',
161         'uri' => '#acl-guest',
162         'resource' => 'nav-guest',
163         'pages' => array(
164             array(
165                 'label' => 'ACL page 1.1 (foo)',
166                 'uri' => '#acl-foo',
167                 'resource' => 'nav-foo'
168             ),
169             array(
170                 'label' => 'ACL page 1.2 (bar)',
171                 'uri' => '#acl-bar',
172                 'resource' => 'nav-bar'
173             ),
174             array(
175                 'label' => 'ACL page 1.3 (baz)',
176                 'uri' => '#acl-baz',
177                 'resource' => 'nav-baz'
178             ),
179             array(
180                 'label' => 'ACL page 1.4 (bat)',
181                 'uri' => '#acl-bat',
182                 'resource' => 'nav-bat'
183             )
184         )
185     ),
186     array(
187         'label' => 'ACL page 2 (member)',
188         'uri' => '#acl-member',
189         'resource' => 'nav-member'
190     ),
191     array(
192         'label' => 'ACL page 3 (admin',
193         'uri' => '#acl-admin',
194         'resource' => 'nav-admin',
195         'pages' => array(
196             array(
197                 'label' => 'ACL page 3.1 (nothing)',
198                 'uri' => '#acl-nada'
199             )
200         )
201     ),
202     array(
203         'label' => 'Zend Framework',
204         'route' => 'zf-route'
205     )
207 ]]></programlisting>
208         </example>
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"?>
216 <config>
217     <nav>
219         <zend>
220             <label>Zend</label>
221             <uri>http://www.zend-project.com/</uri>
222             <order>100</order>
223         </zend>
225         <page1>
226             <label>Page 1</label>
227             <uri>page1</uri>
228             <pages>
230                 <page1_1>
231                     <label>Page 1.1</label>
232                     <uri>page1/page1_1</uri>
233                 </page1_1>
235             </pages>
236         </page1>
238         <page2>
239             <label>Page 2</label>
240             <uri>page2</uri>
241             <pages>
243                 <page2_1>
244                     <label>Page 2.1</label>
245                     <uri>page2/page2_1</uri>
246                 </page2_1>
248                 <page2_2>
249                     <label>Page 2.2</label>
250                     <uri>page2/page2_2</uri>
251                     <pages>
253                         <page2_2_1>
254                             <label>Page 2.2.1</label>
255                             <uri>page2/page2_2/page2_2_1</uri>
256                         </page2_2_1>
258                         <page2_2_2>
259                             <label>Page 2.2.2</label>
260                             <uri>page2/page2_2/page2_2_2</uri>
261                             <active>1</active>
262                         </page2_2_2>
264                     </pages>
265                 </page2_2>
267                 <page2_3>
268                     <label>Page 2.3</label>
269                     <uri>page2/page2_3</uri>
270                     <pages>
272                         <page2_3_1>
273                             <label>Page 2.3.1</label>
274                             <uri>page2/page2_3/page2_3_1</uri>
275                         </page2_3_1>
277                         <page2_3_2>
278                             <label>Page 2.3.2</label>
279                             <uri>page2/page2_3/page2_3_2</uri>
280                             <visible>0</visible>
281                             <pages>
283                                     <page2_3_2_1>
284                                         <label>Page 2.3.2.1</label>
285                                         <uri>page2/page2_3/page2_3_2/1</uri>
286                                         <active>1</active>
287                                     </page2_3_2_1>
289                                     <page2_3_2_2>
290                                         <label>Page 2.3.2.2</label>
291                                         <uri>page2/page2_3/page2_3_2/2</uri>
292                                         <active>1</active>
294                                         <pages>
295                                             <page_2_3_2_2_1>
296                                                 <label>Ignore</label>
297                                                 <uri>#</uri>
298                                                 <active>1</active>
299                                             </page_2_3_2_2_1>
300                                         </pages>
301                                     </page2_3_2_2>
303                             </pages>
304                         </page2_3_2>
306                         <page2_3_3>
307                             <label>Page 2.3.3</label>
308                             <uri>page2/page2_3/page2_3_3</uri>
309                             <resource>admin</resource>
310                             <pages>
312                                     <page2_3_3_1>
313                                         <label>Page 2.3.3.1</label>
314                                         <uri>page2/page2_3/page2_3_3/1</uri>
315                                         <active>1</active>
316                                     </page2_3_3_1>
318                                     <page2_3_3_2>
319                                         <label>Page 2.3.3.2</label>
320                                         <uri>page2/page2_3/page2_3_3/2</uri>
321                                         <resource>guest</resource>
322                                         <active>1</active>
323                                     </page2_3_3_2>
325                             </pages>
326                         </page2_3_3>
328                     </pages>
329                 </page2_3>
331             </pages>
332         </page2>
334         <page3>
335             <label>Page 3</label>
336             <uri>page3</uri>
337             <pages>
339                 <page3_1>
340                     <label>Page 3.1</label>
341                     <uri>page3/page3_1</uri>
342                     <resource>guest</resource>
343                 </page3_1>
345                 <page3_2>
346                     <label>Page 3.2</label>
347                     <uri>page3/page3_2</uri>
348                     <resource>member</resource>
349                     <pages>
351                         <page3_2_1>
352                             <label>Page 3.2.1</label>
353                             <uri>page3/page3_2/page3_2_1</uri>
354                         </page3_2_1>
356                         <page3_2_2>
357                             <label>Page 3.2.2</label>
358                             <uri>page3/page3_2/page3_2_2</uri>
359                             <resource>admin</resource>
360                         </page3_2_2>
362                     </pages>
363                 </page3_2>
365                 <page3_3>
366                     <label>Page 3.3</label>
367                     <uri>page3/page3_3</uri>
368                     <resource>special</resource>
369                     <pages>
371                         <page3_3_1>
372                             <label>Page 3.3.1</label>
373                             <uri>page3/page3_3/page3_3_1</uri>
374                             <visible>0</visible>
375                         </page3_3_1>
377                         <page3_3_2>
378                             <label>Page 3.3.2</label>
379                             <uri>page3/page3_3/page3_3_2</uri>
380                             <resource>admin</resource>
381                         </page3_3_2>
383                     </pages>
384                 </page3_3>
386             </pages>
387         </page3>
389         <home>
390             <label>Home</label>
391             <order>-100</order>
392             <module>default</module>
393             <controller>index</controller>
394             <action>index</action>
395         </home>
397     </nav>
398 </config>
399  */
401 $config = new Zend_Config_Xml('/path/to/navigation.xml', 'nav');
402 $container = new Zend_Navigation($config);
403 ]]></programlisting>
404         </example>
405     </sect2>
407     <sect2 id="zend.navigation.containers.adding">
408         <title>Adding pages</title>
410         <para>
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.
414         </para>
416         <example id="zend.navigation.containers.adding.example">
417             <title>Adding pages to a container</title>
419             <programlisting language="php"><![CDATA[
420 // create container
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/'
438 $pages = array(
439     array(
440         'label'  => 'Save'
441         'action' => 'save',
442     ),
443     array(
444         'label' =>  'Delete',
445         'action' => 'delete'
446     )
449 // add two pages
450 $container->addPages($pages);
452 // remove existing pages and add the given pages
453 $container->setPages($pages);
454 ]]></programlisting>
455         </example>
456     </sect2>
458     <sect2 id="zend.navigation.containers.removing">
459         <title>Removing pages</title>
461         <para>
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.
467         </para>
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(
474     array(
475         'label'  => 'Page 1',
476         'action' => 'page1'
477     ),
478     array(
479         'label'  => 'Page 2',
480         'action' => 'page2',
481         'order'  => 200
482     ),
483     array(
484         'label'  => 'Page 3',
485         'action' => 'page3'
486     )
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
499 // remove all pages
500 $container->removePages();      // removes all pages
501 ]]></programlisting>
502         </example>
503     </sect2>
505     <sect2 id="zend.navigation.containers.finding">
506         <title>Finding pages</title>
508         <para>
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.
521         </para>
523         <para>
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>.
533         </para>
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(
540     array(
541         'label' => 'Page 1',
542         'uri'   => 'page-1',
543         'foo'   => 'bar',
544         'pages' => array(
545             array(
546                 'label' => 'Page 1.1',
547                 'uri'   => 'page-1.1',
548                 'foo'   => 'bar',
549             ),
550             array(
551                 'label' => 'Page 1.2',
552                 'uri'   => 'page-1.2',
553                 'class' => 'my-class',
554             ),
555             array(
556                 'type'   => 'uri',
557                 'label'  => 'Page 1.3',
558                 'uri'    => 'page-1.3',
559                 'action' => 'about'
560             )
561         )
562     ),
563     array(
564         'label'      => 'Page 2',
565         'id'         => 'page_2_and_3',
566         'class'      => 'my-class',
567         'module'     => 'page2',
568         'controller' => 'index',
569         'action'     => 'page1'
570     ),
571     array(
572         'label'      => 'Page 3',
573         'id'         => 'page_2_and_3',
574         'module'     => 'page3',
575         'controller' => 'index'
576     )
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',
587                             'page_2_and_3',
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
617 ]]></programlisting>
618         </example>
619     </sect2>
621     <sect2 id="zend.navigation.containers.iterating">
622         <title>Iterating containers</title>
624         <para>
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.
630         </para>
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
638  */
639 $container = new Zend_Navigation(array(
640     array(
641         'label' => 'Page 1',
642         'uri'   => '#'
643     ),
644     array(
645         'label' => 'Page 2',
646         'uri'   => '#',
647         'pages' => array(
648             array(
649                 'label' => 'Page 2.1',
650                 'uri'   => '#'
651             ),
652             array(
653                 'label' => 'Page 2.2',
654                 'uri'   => '#'
655             )
656         )
657     )
658     array(
659         'label' => 'Page 3',
660         'uri'   => '#'
661     )
664 // Iterate flat using regular foreach:
665 // Output: Page 1, Page 2, Page 3
666 foreach ($container as $page) {
667     echo $page->label;
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) {
676     echo $page->label;
678 ]]></programlisting>
679         </example>
680     </sect2>
682     <sect2 id="zend.navigation.containers.other">
683         <title>Other operations</title>
685         <para>
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>.
690         </para>
692         <para>
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
695             debugging.
696         </para>
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(
703     array(
704         'label' => 'Page 1',
705         'uri'   => '#'
706     ),
707     array(
708         'label' => 'Page 2',
709         'uri'   => '#',
710         'pages' => array(
711             array(
712                 'label' => 'Page 2.1',
713                 'uri'   => '#'
714             ),
715             array(
716                 'label' => 'Page 2.2',
717                'uri'   => '#'
718             )
719         )
720     )
723 var_dump($container->toArray());
725 /* Output:
726 array(2) {
727   [0]=> array(15) {
728     ["label"]=> string(6) "Page 1"
729     ["id"]=> NULL
730     ["class"]=> NULL
731     ["title"]=> NULL
732     ["target"]=> NULL
733     ["rel"]=> array(0) {
734     }
735     ["rev"]=> array(0) {
736     }
737     ["order"]=> NULL
738     ["resource"]=> NULL
739     ["privilege"]=> NULL
740     ["active"]=> bool(false)
741     ["visible"]=> bool(true)
742     ["type"]=> string(23) "Zend_Navigation_Page_Uri"
743     ["pages"]=> array(0) {
744     }
745     ["uri"]=> string(1) "#"
746   }
747   [1]=> array(15) {
748     ["label"]=> string(6) "Page 2"
749     ["id"]=> NULL
750     ["class"]=> NULL
751     ["title"]=> NULL
752     ["target"]=> NULL
753     ["rel"]=> array(0) {
754     }
755     ["rev"]=> array(0) {
756     }
757     ["order"]=> NULL
758     ["resource"]=> NULL
759     ["privilege"]=> NULL
760     ["active"]=> bool(false)
761     ["visible"]=> bool(true)
762     ["type"]=> string(23) "Zend_Navigation_Page_Uri"
763     ["pages"]=> array(2) {
764       [0]=> array(15) {
765         ["label"]=> string(8) "Page 2.1"
766         ["id"]=> NULL
767         ["class"]=> NULL
768         ["title"]=> NULL
769         ["target"]=> NULL
770         ["rel"]=> array(0) {
771         }
772         ["rev"]=> array(0) {
773         }
774         ["order"]=> NULL
775         ["resource"]=> NULL
776         ["privilege"]=> NULL
777         ["active"]=> bool(false)
778         ["visible"]=> bool(true)
779         ["type"]=> string(23) "Zend_Navigation_Page_Uri"
780         ["pages"]=> array(0) {
781         }
782         ["uri"]=> string(1) "#"
783       }
784       [1]=>
785       array(15) {
786         ["label"]=> string(8) "Page 2.2"
787         ["id"]=> NULL
788         ["class"]=> NULL
789         ["title"]=> NULL
790         ["target"]=> NULL
791         ["rel"]=> array(0) {
792         }
793         ["rev"]=> array(0) {
794         }
795         ["order"]=> NULL
796         ["resource"]=> NULL
797         ["privilege"]=> NULL
798         ["active"]=> bool(false)
799         ["visible"]=> bool(true)
800         ["type"]=> string(23) "Zend_Navigation_Page_Uri"
801         ["pages"]=> array(0) {
802         }
803         ["uri"]=> string(1) "#"
804       }
805     }
806     ["uri"]=> string(1) "#"
807   }
810 ]]></programlisting>
811         </example>
812     </sect2>
813 </sect1>