# Использование модульной структуры директорий

## Введение

Определенная соглашением модульная структура директорий позволяет разделять различные приложения MVC в автономные единицы и повторно использовать их с различными фронт-контроллерами. Ниже показан пример такой структуры:

    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/

В этой парадигме имена модулей используются как префиксы к контроллерам в этих модулях. Пример выше содержит три контроллера в модулях: 'Blog_IndexController', 'News_IndexController' и 'News_ListController'. Также определены два глобальных контроллера: 'IndexController' и 'FooController', для них не используются пространства имен. Эта структура директорий будет использоваться для примеров в данном разделе.

### Нет пространств имен в модуле, используемом по умолчанию

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

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

## Определение директорий контроллеров в модулях

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

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

    $front->setControllerDirectory(array(
          'default' => '/path/to/application/controllers',
          'blog'    => '/path/to/application/blog/controllers'
    ));

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

    $front->addControllerDirectory('/path/to/application/news/controllers',
                                   'news');

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

    /**
     * Предполагается следующая структура директорий:
     * application/
     *     modules/
     *         default/
     *             controllers/
     *         foo/
     *             controllers/
     *         bar/
     *             controllers/
     */
    $front->addModuleDirectory('/path/to/application/modules');

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

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

    /**
     * Изменяем поддиректорию для контроллеров на 'con'
     * application/
     *     modules/
     *         default/
     *             con/
     *         foo/
     *             con/
     *         bar/
     *             con/
     */
    $front->setModuleControllerDirectoryName('con');
    $front->addModuleDirectory('/path/to/application/modules');

Вы можете указать, что для модулей не должна использоваться поддиректория для контроллеров путем передачи пустого значения методу `setModuleControllerDirectoryName()`.

## Маршрутизация применительно к модулям

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

- `:module/:controller/:action/*`

- `:controller/:action/*`

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

## Модуль или глобальный контроллер по умолчанию

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

Если требуется всегда использовать глобальное пространство имен, то установите параметр `useGlobalDefault` во фронт-контроллере:

    $front->setParam('useDefaultControllerAlways', true);