Pages | Zend_Navigation Programmer's Reference Guide | Zend_Oauth

# Containers

Containers have methods for adding, retrieving, deleting and iterating pages. Containers implement the » SPL interfaces RecursiveIterator and Countable, meaning that a container can be iterated using the SPL RecursiveIteratorIterator class.

# Creating containers

Zend_Navigation_Container is abstract, and can not be instantiated directly. Use Zend_Navigation if you want to instantiate a container.

Zend_Navigation can be constructed entirely empty, or take an array or a Zend_Config object with pages to put in the container. Each page in the given array/config will eventually be passed to the addPage() method of the container class, which means that each element in the array/config can be an array or a config object, or a Zend_Navigation_Page instance.

Example #1 Creating a container using an array

1. /*
2. * Create a container from an array
3. *
4. * Each element in the array will be passed to
5. * Zend_Navigation_Page::factory() when constructing.
6. */
7. $container = new Zend_Navigation( array (
8. array (
9. 'label' => 'Page 1',
10. 'id' => 'home-link',
11. 'uri' => '/'
12. ),
13. array (
14. 'label' => 'Zend',
15. 'uri' => 'http://www.zend-project.com/',
16. 'order' => 100
17. ),
18. array (
19. 'label' => 'Page 2',
20. 'controller' => 'page2',
21. 'pages' => array (
22. array (
23. 'label' => 'Page 2.1',
24. 'action' => 'page2_1',
25. 'controller' => 'page2',
26. 'class' => 'special-one',
27. 'title' => 'This element has a special class',
28. 'active' => true
29. ),
30. array (
31. 'label' => 'Page 2.2',
32. 'action' => 'page2_2',
33. 'controller' => 'page2',
34. 'class' => 'special-two',
35. 'title' => 'This element has a special class too'
36. )
37. )
38. ),
39. array (
40. 'label' => 'Page 2 with params',
41. 'action' => 'index',
42. 'controller' => 'page2',
43. // specify a param or two
44. 'params' => array (
45. 'format' => 'json',
46. 'foo' => 'bar'
47. )
48. ),
49. array (
50. 'label' => 'Page 2 with params and a route',
51. 'action' => 'index',
52. 'controller' => 'page2',
53. // specify a route name and a param for the route
54. 'route' => 'nav-route-example',
55. 'params' => array (
56. 'format' => 'json'
57. )
58. ),
59. array (
60. 'label' => 'Page 3',
61. 'action' => 'index',
62. 'controller' => 'index',
63. 'module' => 'mymodule',
64. 'reset_params' => false
65. ),
66. array (
67. 'label' => 'Page 4',
68. 'uri' => '#',
69. 'pages' => array (
70. array (
71. 'label' => 'Page 4.1',
72. 'uri' => '/page4',
73. 'title' => 'Page 4 using uri',
74. 'pages' => array (
75. array (
76. 'label' => 'Page 4.1.1',
77. 'title' => 'Page 4 using mvc params',
78. 'action' => 'index',
79. 'controller' => 'page4',
80. // let's say this page is active
81. 'active' => '1'
82. )
83. )
84. )
85. )
86. ),
87. array (
88. 'label' => 'Page 0?',
89. 'uri' => '/setting/the/order/option',
90. // setting order to -1 should make it appear first
91. 'order' => -1
92. ),
93. array (
94. 'label' => 'Page 5',
95. 'uri' => '/',
96. // this page should not be visible
97. 'visible' => false,
98. 'pages' => array (
99. array (
100. 'label' => 'Page 5.1',
101. 'uri' => '#',
102. 'pages' => array (
103. array (
104. 'label' => 'Page 5.1.1',
105. 'uri' => '#',
106. 'pages' => array (
107. array (
108. 'label' => 'Page 5.1.2',
109. 'uri' => '#',
110. // let's say this page is active
111. 'active' => true
112. )
113. )
114. )
115. )
116. )
117. )
118. ),
119. array (
120. 'label' => 'ACL page 1 (guest)',
121. 'uri' => '#acl-guest',
122. 'resource' => 'nav-guest',
123. 'pages' => array (
124. array (
125. 'label' => 'ACL page 1.1 (foo)',
126. 'uri' => '#acl-foo',
127. 'resource' => 'nav-foo'
128. ),
129. array (
130. 'label' => 'ACL page 1.2 (bar)',
131. 'uri' => '#acl-bar',
132. 'resource' => 'nav-bar'
133. ),
134. array (
135. 'label' => 'ACL page 1.3 (baz)',
136. 'uri' => '#acl-baz',
137. 'resource' => 'nav-baz'
138. ),
139. array (
140. 'label' => 'ACL page 1.4 (bat)',
141. 'uri' => '#acl-bat',
142. 'resource' => 'nav-bat'
143. )
144. )
145. ),
146. array (
147. 'label' => 'ACL page 2 (member)',
148. 'uri' => '#acl-member',
149. 'resource' => 'nav-member'
150. ),
151. array (
152. 'label' => 'ACL page 3 (admin',
153. 'uri' => '#acl-admin',
154. 'resource' => 'nav-admin',
155. 'pages' => array (
156. array (
157. 'label' => 'ACL page 3.1 (nothing)',
158. 'uri' => '#acl-nada'
159. )
160. )
161. ),
162. array (
163. 'label' => 'Zend Framework',
164. 'route' => 'zf-route'
165. )
166. ));

Example #2 Creating a container using a config object

1. /* CONTENTS OF /path/to/navigation.xml:
2. <?xml version="1.0" encoding="UTF-8"?>
3. <config>
4. <nav>
6. <zend>
7. <label>Zend</label>
8. <uri>http://www.zend-project.com/</uri>
9. <order>100</order>
10. </zend>
12. <page1>
13. <label>Page 1</label>
14. <uri>page1</uri>
15. <pages>
17. <page1_1>
18. <label>Page 1.1</label>
19. <uri>page1/page1_1</uri>
20. </page1_1>
22. </pages>
23. </page1>
25. <page2>
26. <label>Page 2</label>
27. <uri>page2</uri>
28. <pages>
30. <page2_1>
31. <label>Page 2.1</label>
32. <uri>page2/page2_1</uri>
33. </page2_1>
35. <page2_2>
36. <label>Page 2.2</label>
37. <uri>page2/page2_2</uri>
38. <pages>
40. <page2_2_1>
41. <label>Page 2.2.1</label>
42. <uri>page2/page2_2/page2_2_1</uri>
43. </page2_2_1>
45. <page2_2_2>
46. <label>Page 2.2.2</label>
47. <uri>page2/page2_2/page2_2_2</uri>
48. <active>1</active>
49. </page2_2_2>
51. </pages>
52. </page2_2>
54. <page2_3>
55. <label>Page 2.3</label>
56. <uri>page2/page2_3</uri>
57. <pages>
59. <page2_3_1>
60. <label>Page 2.3.1</label>
61. <uri>page2/page2_3/page2_3_1</uri>
62. </page2_3_1>
64. <page2_3_2>
65. <label>Page 2.3.2</label>
66. <uri>page2/page2_3/page2_3_2</uri>
67. <visible>0</visible>
68. <pages>
70. <page2_3_2_1>
71. <label>Page 2.3.2.1</label>
72. <uri>page2/page2_3/page2_3_2/1</uri>
73. <active>1</active>
74. </page2_3_2_1>
76. <page2_3_2_2>
77. <label>Page 2.3.2.2</label>
78. <uri>page2/page2_3/page2_3_2/2</uri>
79. <active>1</active>
81. <pages>
82. <page_2_3_2_2_1>
83. <label>Ignore</label>
84. <uri>#</uri>
85. <active>1</active>
86. </page_2_3_2_2_1>
87. </pages>
88. </page2_3_2_2>
90. </pages>
91. </page2_3_2>
93. <page2_3_3>
94. <label>Page 2.3.3</label>
95. <uri>page2/page2_3/page2_3_3</uri>
96. <resource>admin</resource>
97. <pages>
99. <page2_3_3_1>
100. <label>Page 2.3.3.1</label>
101. <uri>page2/page2_3/page2_3_3/1</uri>
102. <active>1</active>
103. </page2_3_3_1>
105. <page2_3_3_2>
106. <label>Page 2.3.3.2</label>
107. <uri>page2/page2_3/page2_3_3/2</uri>
108. <resource>guest</resource>
109. <active>1</active>
110. </page2_3_3_2>
112. </pages>
113. </page2_3_3>
115. </pages>
116. </page2_3>
118. </pages>
119. </page2>
121. <page3>
122. <label>Page 3</label>
123. <uri>page3</uri>
124. <pages>
126. <page3_1>
127. <label>Page 3.1</label>
128. <uri>page3/page3_1</uri>
129. <resource>guest</resource>
130. </page3_1>
132. <page3_2>
133. <label>Page 3.2</label>
134. <uri>page3/page3_2</uri>
135. <resource>member</resource>
136. <pages>
138. <page3_2_1>
139. <label>Page 3.2.1</label>
140. <uri>page3/page3_2/page3_2_1</uri>
141. </page3_2_1>
143. <page3_2_2>
144. <label>Page 3.2.2</label>
145. <uri>page3/page3_2/page3_2_2</uri>
146. <resource>admin</resource>
147. </page3_2_2>
149. </pages>
150. </page3_2>
152. <page3_3>
153. <label>Page 3.3</label>
154. <uri>page3/page3_3</uri>
155. <resource>special</resource>
156. <pages>
158. <page3_3_1>
159. <label>Page 3.3.1</label>
160. <uri>page3/page3_3/page3_3_1</uri>
161. <visible>0</visible>
162. </page3_3_1>
164. <page3_3_2>
165. <label>Page 3.3.2</label>
166. <uri>page3/page3_3/page3_3_2</uri>
167. <resource>admin</resource>
168. </page3_3_2>
170. </pages>
171. </page3_3>
173. </pages>
174. </page3>
176. <home>
177. <label>Home</label>
178. <order>-100</order>
179. <module>default</module>
180. <controller>index</controller>
181. <action>index</action>
182. </home>
184. </nav>
185. </config>
186. */
188. $config = new Zend_Config_Xml('/path/to/navigation.xml', 'nav');
189. $container = new Zend_Navigation($config);

# Adding pages

Adding pages to a container can be done with the methods addPage(), addPages(), or setPages(). See examples below for explanation.

Example #3 Adding pages to a container

1. // create container
2. $container = new Zend_Navigation();
4. // add page by giving a page instance
5. $container->addPage(Zend_Navigation_Page::factory( array (
6. 'uri' => 'http://www.example.com/'
7. )))
9. // add page by giving an array
10. $container->addPage( array (
11. 'uri' => 'http://www.example.com/'
12. )))
14. // add page by giving a config object
15. $container->addPage(new Zend_Config( array (
16. 'uri' => 'http://www.example.com/'
17. )))
19. $pages = array (
20. array (
21. 'label' => 'Save'
22. 'action' => 'save',
23. ),
24. array (
25. 'label' => 'Delete',
26. 'action' => 'delete'
27. )
28. );
30. // add two pages
31. $container->addPages($pages);
33. // remove existing pages and add the given pages
34. $container->setPages($pages);

# Removing pages

Removing pages can be done with removePage() or removePages(). The first method accepts a an instance of a page, or an integer. The integer corresponds to the `order` a page has. The latter method will remove all pages in the container.

Example #4 Removing pages from a container

1. $container = new Zend_Navigation( array (
2. array (
3. 'label' => 'Page 1',
4. 'action' => 'page1'
5. ),
6. array (
7. 'label' => 'Page 2',
8. 'action' => 'page2',
9. 'order' => 200
10. ),
11. array (
12. 'label' => 'Page 3',
13. 'action' => 'page3'
14. )
15. ));
17. // remove page by implicit page order
18. $container->removePage(0); // removes Page 1
20. // remove page by instance
21. $page3 = $container->findOneByAction('Page 3');
22. $container->removePage($page3); // removes Page 3
24. // remove page by explicit page order
25. $container->removePage(200); // removes Page 2
27. // remove all pages
28. $container->removePages(); // removes all pages

# Finding pages

Containers have finder methods for retrieving pages. They are findOneBy($property, $value), findAllBy($property, $value), and findBy($property, $value, $all = false). Those methods will recursively search the container for pages matching the given `$page->$property == $value`. The first method, findOneBy(), will return a single page matching the property with the given value, or `NULL` if it cannot be found. The second method will return all pages with a property matching the given value. The third method will call one of the two former methods depending on the $all flag.

The finder methods can also be used magically by appending the property name to `findBy`, `findOneBy`, or `findAllBy`, e.g. findOneByLabel('Home') to return the first matching page with label `Home`. Other combinations are findByLabel(...), findOnyByTitle(...), findAllByController(...), etc. Finder methods also work on custom properties, such as findByFoo('bar').

Example #5 Finding pages in a container

1. $container = new Zend_Navigation( array (
2. array (
3. 'label' => 'Page 1',
4. 'uri' => 'page-1',
5. 'foo' => 'bar',
6. 'pages' => array (
7. array (
8. 'label' => 'Page 1.1',
9. 'uri' => 'page-1.1',
10. 'foo' => 'bar',
11. ),
12. array (
13. 'label' => 'Page 1.2',
14. 'uri' => 'page-1.2',
15. 'class' => 'my-class',
16. ),
17. array (
18. 'type' => 'uri',
19. 'label' => 'Page 1.3',
20. 'uri' => 'page-1.3',
21. 'action' => 'about'
22. )
23. )
24. ),
25. array (
26. 'label' => 'Page 2',
27. 'id' => 'page_2_and_3',
28. 'class' => 'my-class',
29. 'module' => 'page2',
30. 'controller' => 'index',
31. 'action' => 'page1'
32. ),
33. array (
34. 'label' => 'Page 3',
35. 'id' => 'page_2_and_3',
36. 'module' => 'page3',
37. 'controller' => 'index'
38. )
39. ));
41. // The 'id' is not required to be unique, but be aware that
42. // having two pages with the same id will render the same id attribute
43. // in menus and breadcrumbs.
44. $found = $container->findBy('id',
45. 'page_2_and_3'); // returns Page 2
46. $found = $container->findOneBy('id',
47. 'page_2_and_3'); // returns Page 2
48. $found = $container->findBy('id',
49. 'page_2_and_3',
50. true); // returns Page 2 and Page 3
51. $found = $container->findById('page_2_and_3'); // returns Page 2
52. $found = $container->findOneById('page_2_and_3'); // returns Page 2
53. $found = $container->findAllById('page_2_and_3'); // returns Page 2 and Page 3
55. // Find all matching CSS class my-class
56. $found = $container->findAllBy('class',
57. 'my-class'); // returns Page 1.2 and Page 2
58. $found = $container->findAllByClass('my-class'); // returns Page 1.2 and Page 2
60. // Find first matching CSS class my-class
61. $found = $container->findOneByClass('my-class'); // returns Page 1.2
63. // Find all matching CSS class non-existant
64. $found = $container->findAllByClass('non-existant'); // returns array()
66. // Find first matching CSS class non-existant
67. $found = $container->findOneByClass('non-existant'); // returns null
69. // Find all pages with custom property 'foo' = 'bar'
70. $found = $container->findAllBy('foo', 'bar'); // returns Page 1 and Page 1.1
72. // To achieve the same magically, 'foo' must be in lowercase.
73. // This is because 'foo' is a custom property, and thus the
74. // property name is not normalized to 'Foo'
75. $found = $container->findAllByfoo('bar');
77. // Find all with controller = 'index'
78. $found = $container->findAllByController('index'); // returns Page 2 and Page 3

# Iterating containers

Zend_Navigation_Container implements RecursiveIteratorIterator, and can be iterated using any Iterator class. To iterate a container recursively, use the RecursiveIteratorIterator class.

Example #6 Iterating a container

1. /*
2. * Create a container from an array
3. */
4. $container = new Zend_Navigation( array (
5. array (
6. 'label' => 'Page 1',
7. 'uri' => '#'
8. ),
9. array (
10. 'label' => 'Page 2',
11. 'uri' => '#',
12. 'pages' => array (
13. array (
14. 'label' => 'Page 2.1',
15. 'uri' => '#'
16. ),
17. array (
18. 'label' => 'Page 2.2',
19. 'uri' => '#'
20. )
21. )
22. )
23. array (
24. 'label' => 'Page 3',
25. 'uri' => '#'
26. )
27. ));
29. // Iterate flat using regular foreach:
30. // Output: Page 1, Page 2, Page 3
31. foreach ($container as $page) {
32. echo $page->label;
33. }
35. // Iterate recursively using RecursiveIteratorIterator
36. $it = new RecursiveIteratorIterator(
37. $container, RecursiveIteratorIterator::SELF_FIRST);
39. // Output: Page 1, Page 2, Page 2.1, Page 2.2, Page 3
40. foreach ($it as $page) {
41. echo $page->label;
42. }

# Other operations

The method hasPage(Zend_Navigation_Page $page) checks if the container has the given page. The method hasPages() checks if there are any pages in the container, and is equivalent to `count($container) > 1`.

The toArray() method converts the container and the pages in it to an array. This can be useful for serializing and debugging.

Example #7 Converting a container to an array

1. $container = new Zend_Navigation( array (
2. array (
3. 'label' => 'Page 1',
4. 'uri' => '#'
5. ),
6. array (
7. 'label' => 'Page 2',
8. 'uri' => '#',
9. 'pages' => array (
10. array (
11. 'label' => 'Page 2.1',
12. 'uri' => '#'
13. ),
14. array (
15. 'label' => 'Page 2.2',
16. 'uri' => '#'
17. )
18. )
19. )
20. ));
22. var_dump ($container->toArray());
24. /* Output:
25. array(2) {
26. [0]=> array(15) {
27. ["label"]=> string(6) "Page 1"
28. ["id"]=> NULL
29. ["class"]=> NULL
30. ["title"]=> NULL
31. ["target"]=> NULL
32. ["rel"]=> array(0) {
33. }
34. ["rev"]=> array(0) {
35. }
36. ["order"]=> NULL
37. ["resource"]=> NULL
38. ["privilege"]=> NULL
39. ["active"]=> bool(false)
40. ["visible"]=> bool(true)
41. ["type"]=> string(23) "Zend_Navigation_Page_Uri"
42. ["pages"]=> array(0) {
43. }
44. ["uri"]=> string(1) "#"
45. }
46. [1]=> array(15) {
47. ["label"]=> string(6) "Page 2"
48. ["id"]=> NULL
49. ["class"]=> NULL
50. ["title"]=> NULL
51. ["target"]=> NULL
52. ["rel"]=> array(0) {
53. }
54. ["rev"]=> array(0) {
55. }
56. ["order"]=> NULL
57. ["resource"]=> NULL
58. ["privilege"]=> NULL
59. ["active"]=> bool(false)
60. ["visible"]=> bool(true)
61. ["type"]=> string(23) "Zend_Navigation_Page_Uri"
62. ["pages"]=> array(2) {
63. [0]=> array(15) {
64. ["label"]=> string(8) "Page 2.1"
65. ["id"]=> NULL
66. ["class"]=> NULL
67. ["title"]=> NULL
68. ["target"]=> NULL
69. ["rel"]=> array(0) {
70. }
71. ["rev"]=> array(0) {
72. }
73. ["order"]=> NULL
74. ["resource"]=> NULL
75. ["privilege"]=> NULL
76. ["active"]=> bool(false)
77. ["visible"]=> bool(true)
78. ["type"]=> string(23) "Zend_Navigation_Page_Uri"
79. ["pages"]=> array(0) {
80. }
81. ["uri"]=> string(1) "#"
82. }
83. [1]=>
84. array(15) {
85. ["label"]=> string(8) "Page 2.2"
86. ["id"]=> NULL
87. ["class"]=> NULL
88. ["title"]=> NULL
89. ["target"]=> NULL
90. ["rel"]=> array(0) {
91. }
92. ["rev"]=> array(0) {
93. }
94. ["order"]=> NULL
95. ["resource"]=> NULL
96. ["privilege"]=> NULL
97. ["active"]=> bool(false)
98. ["visible"]=> bool(true)
99. ["type"]=> string(23) "Zend_Navigation_Page_Uri"
100. ["pages"]=> array(0) {
101. }
102. ["uri"]=> string(1) "#"
103. }
104. }
105. ["uri"]=> string(1) "#"
106. }
107. }
108. */

Pages | Zend_Navigation Programmer's Reference Guide | Zend_Oauth