<sect1 id="zend.controller.modular">
    <title>Использование определенной соглашением модульной структуры директорий</title>

    <sect2 id="zend.controller.modular.introduction">
        <title>Введение</title>
        <para>
            Определенная соглашением модульная структура директорий позволяет
            разделять различные приложения MVC в автономные единицы и повторно
            использовать их с различными фронт-контроллерами. Ниже показан
            пример такой структуры:
        </para>

        <programlisting>
<![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>
            В этой парадигме имена модулей используются как префиксы к
            контроллерам в этих модулях. Пример выше содержит три контроллера в
            модулях: 'Blog_IndexController', 'News_IndexController' и
            'News_ListController'. Также определены два глобальных контроллера:
            'IndexController' и 'FooController', для них не используются
            пространства имен. Эта структура директорий будет
            использоваться для примеров в данном разделе.
        </para>

        <note>
            <title>Нет пространств имен в модуле, используемом по умолчанию</title>
            <para>
                Обратите внимание, что в модуле, используемом по умолчанию,
                контролеры не нуждаются в префиксе пространства имен. В примере
                выше контроллеры в модуле по умолчанию не нуждаются в префиксе
                'Default_' - они просто вызываются по их базовым именам
                контроллера: 'IndexController' and 'FooController'. Но для
                других модулей использование префикса пространства имен
                обязательно.
            </para>
        </note>

        <para>
            Итак, как можно реализовать такую организацию на уровне директорий,
            используя компоненты MVC в Zend Framework?
        </para>
    </sect2>

    <sect2 id="zend.controller.modular.directories">
        <title>Определение директорий контроллеров в модулях</title>

        <para>
            Первым шагом в использовании модулей является изменение способа
            определения списка директорий во фронт-контроллере. При обычном
            использовании MVC вы передаете массив или строку методу
            <code>setControllerDirectory()</code>, либо путь методу
            <code>addControllerDirectory()</code>. В случае использования
            модулей нужно несколько изменить вызовы этих методов.
        </para>

        <para>
            Методу <code>setControllerDirectory()</code> должен передаваться
            ассоциативный массив, в котором пары ключ/значение содержат имя
            модуля и путь к директории соответственно. Специальный ключ
            'default' используется для глобальных контроллеров (которым не нужно
            пространство имен модуля). Все записи должны содержать строковой
            ключ, указывающий на единственный путь, при этом должен
            присутствовать ключ <code>default</code>. Например:
        </para>

        <programlisting role="php"><![CDATA[
$front->setControllerDirectory(array(
      'default' => '/path/to/application/controllers',
      'blog'    => '/path/to/application/blog/controllers'
));
]]>
        </programlisting>

        <para>
            Метод <code>addControllerDirectory()</code> принимает необязательный
            второй параметр. Если используются модули, то передавайте имя модуля
            в качестве второго аргумента; если он не определен, то путь будет
            добавлен в пространство имен <code>default</code>. Например:
        </para>

        <programlisting role="php"><![CDATA[
$front->addControllerDirectory('/path/to/application/news/controllers',
                               'news');
]]>
        </programlisting>

        <para>
            Лучшее напоследок: самый легкий способ определения
            директорий модулей состоит в их одновременном определении, со всеми
            модулями под общей директорией и использующими одну и ту же
            структуру. Это может быть сделано с помощью
            <code>addModuleDirectory()</code>:
        </para>

        <programlisting role="php"><![CDATA[
/**
 * Предполагается следующая структура директорий:
 * application/
 *     modules/
 *         default/
 *             controllers/
 *         foo/
 *             controllers/
 *         bar/
 *             controllers/
 */
$front->addModuleDirectory('/path/to/application/modules');
]]>
        </programlisting>

        <para>
            Пример выше определит модули <code>default</code>, <code>foo</code>
            и <code>bar</code>, все они указывают на поддиректорию
            <code>controllers</code> соответствующих модулей.
        </para>

        <para>
            Через метод <code>setModuleControllerDirectoryName() можно указать
            другую поддиректорию контроллеров для использования внутри
            модулей</code>:
        </para>

        <programlisting role="php"><![CDATA[
/**
 * Изменяем поддиректорию для контроллеров на 'con'
 * application/
 *     modules/
 *         default/
 *             con/
 *         foo/
 *             con/
 *         bar/
 *             con/
 */
$front->setModuleControllerDirectoryName('con');
$front->addModuleDirectory('/path/to/application/modules');
]]>
        </programlisting>

        <note><para>
            Вы можете указать, что для модулей не должна использоваться
            поддиректория для контроллеров путем передачи пустого значения
            методу <code>setModuleControllerDirectoryName()</code>.
        </para></note>
    </sect2>

    <sect2 id="zend.controller.modular.router">
        <title>Маршрутизация применительно к модулям</title>

        <para>
            Маршрут, используемый по умолчанию в
            <code>Zend_Controller_Router_Rewrite</code>, является объектом типа
            <code>Zend_Controller_Router_Route_Module</code>. Этот маршрут
            использует один из следующих шаблонов маршрутизации:
        </para>

        <itemizedlist>
            <listitem><para>
                <code>:module/:controller/:action/*</code>
            </para></listitem>
            <listitem><para>
                <code>:controller/:action/*</code>
            </para></listitem>
        </itemizedlist>

        <para>
            Другими словами, он будет соответсвовать контроллеру и действию без
            модуля или контроллеру и действию с предшествующим модулем. Правила
            сопоставления предписывают, что URL должен только тогда
            соответствовать модулю, если ключ с тем же именем существует в
            массиве директорий контроллеров, переданного фронт-контроллеру и
            диспетчеру.
        </para>
    </sect2>

    <sect2 id="zend.controller.modular.defaultcontroller">
        <title>Молуль или глобальный контроллер по умолчанию</title>

        <para>
            В маршрутизаторе, используемом по умолчанию, если контроллер не был
            указан в URL, то используется контроллер по умолчанию
            (<code>IndexController</code>, если не был установлен другой). В
            случае использования модулей, если был указан модуль без
            контроллера, то диспетчер сначала ищет используемый по умолчанию
            контроллер в директории модуля, затем в глобальном пространстве имен
            'default'.
        </para>

        <para>
            Если хотите всегда использовать глобальное пространство имен, то
            установите параметр <code>useGlobalDefault</code> во
            фронт-контроллере:
        </para>

        <programlisting role="php"><![CDATA[
$front->setParam('useDefaultControllerAlways', true);
]]>
        </programlisting>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
