1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
|
<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<sect1 id="zend.controller.modular">
<title>Using a Conventional Modular Directory Structure</title>
<sect2 id="zend.controller.modular.introduction">
<title>Introduction</title>
<para>
The Conventional Modular directory structure allows you to separate
different <acronym>MVC</acronym> applications into self-contained units, and re-use
them with different front controllers. To illustrate such a
directory structure:
</para>
<programlisting language="txt"><![CDATA[
docroot/
index.php
application/
default/
controllers/
IndexController.php
FooController.php
models/
views/
scripts/
index/
foo/
helpers/
filters/
blog/
controllers/
IndexController.php
models/
views/
scripts/
index/
helpers/
filters/
news/
controllers/
IndexController.php
ListController.php
models/
views/
scripts/
index/
list/
helpers/
filters/
]]></programlisting>
<para>
In this paradigm, the module name serves as a prefix to the
controllers it contains. The above example contains three
module controllers, '<classname>Blog_IndexController</classname>',
'<classname>News_IndexController</classname>', and
'<classname>News_ListController</classname>'.
Two global controllers, '<classname>IndexController</classname>' and
'<classname>FooController</classname>' are also defined; neither of these will be
namespaced. This directory structure will be used for examples in
this chapter.
</para>
<note>
<title>No Namespacing in the Default Module</title>
<para>
Note that in the default module, controllers do not need a
namespace prefix. Thus, in the example above, the controllers in
the default module do not need a prefix of 'Default_' -- they
are simply dispatched according to their base controller name:
'<classname>IndexController</classname>' and
'<classname>FooController</classname>'. A namespace prefix is
used in all other modules, however.
</para>
</note>
<para>
So, how do you implement such a directory layout using the Zend
Framework <acronym>MVC</acronym> components?
</para>
</sect2>
<sect2 id="zend.controller.modular.directories">
<title>Specifying Module Controller Directories</title>
<para>
The first step to making use of modules is to modify how you specify
the controller directory list in the front controller. In the basic
<acronym>MVC</acronym> series, you pass either an array or a string to
<methodname>setControllerDirectory()</methodname>, or a path to
<methodname>addControllerDirectory()</methodname>. When using modules, you need
to alter your calls to these methods slightly.
</para>
<para>
With <methodname>setControllerDirectory()</methodname>, you will need to pass an
associative array and specify key and value pairs of module
name and directory paths. The special key <property>default</property> will be
used for global controllers (those not needing a module namespace).
All entries should contain a string key pointing to a single path,
and the <property>default</property> key must be present. As an example:
</para>
<programlisting language="php"><![CDATA[
$front->setControllerDirectory(array(
'default' => '/path/to/application/controllers',
'blog' => '/path/to/application/blog/controllers'
));
]]></programlisting>
<para>
<methodname>addControllerDirectory()</methodname> will take an optional second
argument. When using modules, pass the module name as the second
argument; if not specified, the path will be added to the
<emphasis>default</emphasis> namespace. As an example:
</para>
<programlisting language="php"><![CDATA[
$front->addControllerDirectory('/path/to/application/news/controllers',
'news');
]]></programlisting>
<para>
Saving the best for last, the easiest way to specify module
directories is to do so en masse, with all modules under a common
directory and sharing the same structure. This can be done with
<methodname>addModuleDirectory()</methodname>:
</para>
<programlisting language="php"><![CDATA[
/**
* Assuming the following directory structure:
* application/
* modules/
* default/
* controllers/
* foo/
* controllers/
* bar/
* controllers/
*/
$front->addModuleDirectory('/path/to/application/modules');
]]></programlisting>
<para>
The above example will define the <emphasis>default</emphasis>,
<emphasis>foo</emphasis>, and <emphasis>bar</emphasis> modules, each pointing to the
<filename>controllers/</filename> subdirectory of their respective module.
</para>
<para>
You may customize the controller subdirectory to use within your
modules by using <methodname>setModuleControllerDirectoryName()</methodname>:
</para>
<programlisting language="php"><![CDATA[
/**
* Change the controllers subdirectory to be 'con'
* application/
* modules/
* default/
* con/
* foo/
* con/
* bar/
* con/
*/
$front->setModuleControllerDirectoryName('con');
$front->addModuleDirectory('/path/to/application/modules');
]]></programlisting>
<note>
<para>
You can indicate that no controller subdirectory be used for your
modules by passing an empty value to
<methodname>setModuleControllerDirectoryName()</methodname>.
</para>
</note>
</sect2>
<sect2 id="zend.controller.modular.router">
<title>Routing to Modules</title>
<para>
The default route in <classname>Zend_Controller_Router_Rewrite</classname> is
an object of type <classname>Zend_Controller_Router_Route_Module</classname>.
This route expects one of the following routing schemas:
</para>
<itemizedlist>
<listitem><para><filename>:module/:controller/:action/*</filename></para></listitem>
<listitem><para><filename>:controller/:action/*</filename></para></listitem>
</itemizedlist>
<para>
In other words, it will match a controller and action by themselves
or with a preceding module. The rules for matching specify that a
module will only be matched if a key of the same name exists in the
controller directory array passed to the front controller and
dispatcher.
</para>
</sect2>
<sect2 id="zend.controller.modular.defaultcontroller">
<title>Module or Global Default Controller</title>
<para>
In the default router, if a controller was not specified in the <acronym>URL</acronym>,
a default controller is used (<classname>IndexController</classname>, unless
otherwise requested). With modular controllers, if a module has been
specified but no controller, the dispatcher first looks for this
default controller in the module path, and then falls back on the
default controller found in the 'default', global, namespace.
</para>
<para>
If you wish to always default to the global namespace, set the
<varname>$useDefaultControllerAlways</varname> parameter in the front controller:
</para>
<programlisting language="php"><![CDATA[
$front->setParam('useDefaultControllerAlways', true);
]]></programlisting>
</sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
|