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
を使用する利点のひとつに、
共通の規約に従ったアプリケーションを作成できるということがあります。
デフォルトの振る舞いをあまりにも変更してしまうと、この利点が失われてしまいます。
しかしながら、世の中にはさまざまな需要があるわけですし、
ひとつのソリューションですべて解決できるわけがありません。
そのために、必要なら変更できるようにしています。
Zend_Controller のクラスを継承する場合は、 その命名や保存場所はできるだけ次の規約に従うようにしてください。 そうすることで、Zend Framework になじみのある他のプログラマが、 あなたのプロジェクトの内容を簡単に理解できるようになります。
Zend Framework に含まれるクラスの名前は、すべて "Zend_" で始まっています。これがプレフィックスです。 あなたが作成するクラスも同じようにしておくことを推奨します。 例えば、もしあなたの所属する会社名が Widget, Inc. なら、 プレフィックスを "Widget_" とします。
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
ファイルを置き、
変更点や動作内容を簡単に説明しておくようにしましょう。
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()
を提供しています。
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 は、この後でやるべきことがもうないということを意味します。