# モジュラーディレクトリ構造の規約の使用

## 導入

モジュラーディレクトリ構造の規約 (The Conventional Modular directory structure) により、さまざまな 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' および 'FooController' にもとづいて単純にディスパッチされます。 しかし、それ以外のモジュールでは名前空間プレフィックスを使用します。

それでは、Zend Framework の MVC コンポーネントを使用して これらのディレクトリ配置を実装するにはどうすればいいのでしょうか?

## モジュールコントローラディレクトリの指定

モジュールを使用するための第一歩となるのが、 フロントコントローラでのコントローラディレクトリの設定方法を変更することです。 基本的な 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 で指定されなかった場合には デフォルトのコントローラ (特に指定しなければ IndexController) を使用します。モジュール対応のコントローラにおいて、 モジュールのみを指定してコントローラを指定しなかった場合は、 ディスパッチャはまず最初にモジュールパス内のデフォルトコントローラを探します。 次に、グローバル名前空間 'default' にあるデフォルトコントローラを探します。

デフォルトは常にグローバル名前空間のほうにしたい場合は、 フロントコントローラでパラメータ `$useDefaultControllerAlways` を指定します。

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