4.3. サブクラス化
前のページ | 第4章 Zend_Controller | 次のページ

## 4.3. サブクラス化

### 4.3.1. 導入

`Zend_Controller` システムは、拡張性を考慮して作成されています。 拡張方法としては、既存のクラスを継承する以外にも `Zend_Controller_Router_Interface` および `Zend_Controller_Dispatcher_Interface` を実装した新しいクラスを作成する方法があります。

新しいルータやディスパッチャを実装する理由としては、 以下のようなものが考えられるでしょう。

- 既存の URI ルーティングが何らかの理由で適用できない場合。 例えば、既存のウェブサイトと統合する予定であるが、 そこで採用している規約が Zend Framework のルーティング機構と合致しないなど。

- まったく別のルーティングを実装しなければならない場合。 `Zend_Controller_Router` クラスは URI のみを対象としています。 例えばコンソールアプリケーションなどの別の形式のプログラムにも MVC パターンを使用したくなることもあるでしょう。 コンソールアプリケーションの場合なら、 独自のルータを実装してコマンドライン引数によるルーティングを行うことになるでしょう。

- `Zend_Controller_Dispatcher` の提供する機能がうまく当てはまらない場合。 デフォルト設定では、コントローラはクラスであり、 アクションはクラスのメソッドであることを前提としています。 しかし、これ以外にもいろいろなやり方があるでしょう。 例えば、ディレクトリをコントローラ、 ディレクトリ内のファイルをアクションと考えることもできます。

- すべてのコントローラで使用するための機能を追加したい場合。 例えば、デフォルトでは `Zend_Controller_Action` は `Zend_View` と統合されていません。しかし、 コントローラを継承したクラスでこの機能を持たせることができます。 そうすれば、もとの `Zend_Controller_Router` や `Zend_Controller_Dispatcher` に手を加えずにすみます。

システムの主要な部分、特にディスパッチャをオーバーライドする際には十分注意してください。 `Zend_Controller` を使用する利点のひとつに、 共通の規約に従ったアプリケーションを作成できるということがあります。 デフォルトの振る舞いをあまりにも変更してしまうと、この利点が失われてしまいます。 しかしながら、世の中にはさまざまな需要があるわけですし、 ひとつのソリューションですべて解決できるわけがありません。 そのために、必要なら変更できるようにしています。

### 4.3.2. 規約

Zend_Controller のクラスを継承する場合は、 その命名や保存場所はできるだけ次の規約に従うようにしてください。 そうすることで、Zend Framework になじみのある他のプログラマが、 あなたのプロジェクトの内容を簡単に理解できるようになります。

#### 4.3.2.1. プレフィックス

Zend Framework に含まれるクラスの名前は、すべて "Zend_" で始まっています。これがプレフィックスです。 あなたが作成するクラスも同じようにしておくことを推奨します。 例えば、もしあなたの所属する会社名が Widget, Inc. なら、 プレフィックスを "Widget_" とします。

#### 4.3.2.2. ディレクトリ構成

`Zend_Controller` クラスは、 ライブラリディレクトリに以下のように格納されます。

    /library
      /Zend
        /Controller
          Action.php
          Dispatcher.php
          Router.php

`Zend_Controller` クラスを継承する場合は、 作成したクラスを (あなたのプレフィックスのもとで) 同じ構造で格納することを推奨します。こうすることで、 あなたのプロジェクトのコードをレビューする人たちがそれを見つけやすくなるでしょう。

例えば Widget, Inc. のプロジェクトがルータのみを独自に実装した場合は、 次のようになるでしょう。

    /library
      /Zend
      /Widget
        /Controller
          Router.php
          README.txt

この例では、`Widget/Controller/` ディレクトリが `Zend/Controller/` ディレクトリと同じ構造になっていることに注意しましょう。 この場合、このファイルでは `Widget_Controller_Router` というクラスが提供されます。このクラスは `Zend_Controller_Router` を継承したものか、あるいは `Zend_Controller_Router_Interface` を実装した独自のクラスとなります。

また、上の例で `Widget/Controller/` ディレクトリに `README.txt` があることにも注意してください。 あなたのプロジェクトを顧客に提供する際には、 それに関する単体テストや文書も作成するよう、Zend は強く推奨します。 そこまではいかなくても、同じディレクトリにシンプルな `README.txt` ファイルを置き、 変更点や動作内容を簡単に説明しておくようにしましょう。

### 4.3.3. ルータのインターフェイス

`Zend_Controller_Router_Interface` で定義されているメソッドは 1 つだけです。

    <?php

      /**
       * @param  Zend_Controller_Dispatcher_Interface
       * @throws Zend_Controller_Router_Exception
       * @return Zend_Controller_Dispatcher_Token|boolean
       */
      public function route(Zend_Controller_Dispatcher_Interface $dispatcher);

    ?>

ルーティングが発生するのは、システムが最初にリクエストを受け取ったときだけです。 ルータの役割は、`Zend_Controller_Dispatch_Token` を生成してコントローラとアクションを指定することです。 その後、これをディスパッチャに渡します。 もしディスパッチトークンが作成できなかった場合は `FALSE` を返さなければなりません。

ディスパッチャの中には、生成されたディスパッチトークンが本当にディスパッチ可能なのかを、 動的な要因をもとにして事前に調べるものもあります。 このため、ルータは、`route()` の唯一の引数としてディスパッチャのオブジェクトハンドルを受け取ります。 ディスパッチャは、これを確かめるためのメソッドとして `isDispatchable()` を提供しています。

### 4.3.4. ディスパッチャのインターフェイス

`Zend_Controller_Front` は、 まず最初にルータをコールしてディスパッチトークンを取得し、 それをディスパッチャに渡します。ディスパッチャはアクションを起動 (コントローラのインスタンスを作成し、そのアクションをコール) し、論理型の FALSE あるいは別のディスパッチトークンのどちらかを返します。

`Zend_Controller_Front` は、 ディスパッチトークンが返されなくなるまで、 ディスパッチャを繰り返しコールします。これが、いわゆるディスパッチループです。 これにより、アクションが処理を順にすすめていけるようになります。

`Zend_Controller_Dispatcher_Interface` では 2 つのメソッドが定義されています。

    <?php

    /**
     * @param  Zend_Controller_Dispatcher_Token $route
     * @return boolean
     */
    public function isDispatchable(Zend_Controller_Dispatcher_Token $route);

    ?>

`isDispatchable()` は、 ディスパッチトークンが実際にディスパッチ可能かどうかを調べます。 ディスパッチ可能な場合に `TRUE`、それ以外の場合に `FALSE` を返します。ディスパッチ可能かどうかを判断する基準は、 インターフェリスを実装したクラスで記述します。 デフォルトの実装である `Zend_Controller_Dispatcher` では、 コントローラのファイルが存在するかどうか、 そのファイルでクラスが定義されているかどうか、 そしてそのクラスでアクションメソッドが定義されているかどうかを調べます。

    <?php

    /**
     * @param  Zend_Controller_Dispatcher_Token $route
     * @return Zend_Controller_Dispatcher_Token|boolean
     */
    public function dispatch(Zend_Controller_Dispatcher_Token $route);

    ?>

`dispatch()` は、実際の処理を行うところです。 このメソッドは、コントローラのアクションを実行しなければなりません。 また、ディスパッチトークンあるいは論理型の FALSE のいずれかを返さなければなりません。 FALSE は、この後でやるべきことがもうないということを意味します。

前のページ | 上に戻る | 次のページ
4.2. さあ、はじめましょう | ホーム | 4.4. プラグイン