MVC コンポーネントの API は以前とは変更されました。 初期のバージョンから Zend Framework を使用しておられるかたは、 以下のガイドラインにしたがってスクリプトを変更し、 新しい仕組みに対応させてください。
1.0.0RC1 での最大の変更点は、 ErrorHandler プラグインと ViewRenderer アクションヘルパーが追加され、デフォルトで有効となったことです。 それぞれのドキュメントを熟読し、どのように動作するのかや 既存のアプリケーションに与える影響について確認しておきましょう。
ErrorHandler
プラグインは
postDispatch()
で動作するもので、
例外をチェックして指定したエラーハンドラコントローラに転送します。
そのため、アプリケーション内にエラー処理用コントローラを含める必要があります。
このプラグインを無効にするには、フロントコントローラのパラメータ
noErrorHandler
を設定します。
<?php $front->setParam('noErrorHandler', true);
ViewRenderer
アクションヘルパーは、
アクションコントローラへのビューの注入を自動的に行います。
また、現在のアクションにもとづいたビュースクリプトを自動的にレンダリングします。
ビュースクリプトをレンダリングせず、かつ転送やリダイレクトも行わないアクションがあった場合、
これは問題になるでしょう。というのも、
ViewRenderer
はそんなアクションであっても
アクション名をもとに自動的にビュースクリプトをレンダリングしようとするからです。
もし既存のコードにそのようなものがあった場合の対応方法はいくつか考えられます。
一番手っ取り早いのは、フロントコントローラの起動時に
ViewRenderer
を無効にしてからディスパッチを行うことです。
<?php // $front は Zend_Controller_Front のインスタンスであるとします $front->setParam('noViewRenderer', true);
しかし、長い目で見ればこれはあまりよい作戦ではありません。 今後も新しいコードを書き続けるならなおさらです。
ViewRenderer の機能を把握したら、コントローラのコードを見てみましょう。 まず、アクションメソッド (名前が 'Action' で終わっているメソッド) を探し、その中でどんな処理をしているかを確認しましょう。 もし次に挙げるいずれの内容も行っていない場合は、コードに手を加える必要があります。
$this->render()
のコール
$this->_forward()
のコール
$this->_redirect()
のコール
Redirector アクションヘルパーのコール
一番簡単なのは、そのメソッド内で自動レンダリングを無効にすることです。
$this->_helper->viewRenderer->setNoRender();
レンダリング、転送あるいはリダイレクトを行っているアクションメソッドがひとつもない場合は、
上で示したコードを preDispatch()
メソッドあるいは init()
メソッド内に書くといいでしょう。
public function preDispatch() { // ビュースクリプトの自動レンダリングを無効にします $this->_helper->viewRenderer->setNoRender() // .. 何かほかのことをします... }
もしメソッド内で render()
をコールしていて、
規約どおりのディレクトリ構造
を使用しているのなら、自動レンダリングを使用するようにコードを書き換えましょう。
ひとつのアクションで複数のビュースクリプトをレンダリングしている場合は、 なにも変更する必要はありません。
何も引数を指定せずに render()
をコールしている場合は、
その行を削除します。
引数つきで render()
をコールしていて、
その後に何か処理をしたり複数のビュースクリプトを実行したりしていない場合は、
その行を
$this->_helper->viewRenderer()
のように変更します。
独自のディレクトリ構造を使用している場合は、
ビューの基底パスやスクリプトのパスをメソッドで設定してから
ViewRenderer
を使用します。これらのメソッドについての詳細は
ViewRenderer
のドキュメント を参照ください。
ビューオブジェクトをレジストリから取得していたり
ビューオブジェクトをカスタマイズしていたり、
あるいはデフォルトとは異なるビューを使用している場合は、
そのオブジェクトを ViewRenderer
に注入するために次のようにします。
これはいつでも好きなときに行えます。
フロントコントローラのインスタンスを最初に作成する前なら
<?php // $view はすでに定義されているものとします $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view); Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
フロントコントローラのインスタンスを取得した後なら
<?php $viewRenderer = Zend_Controller_Action_HelperBroker::getExistingHelper('viewRenderer'); $viewRenderer->setView($view);
ViewRenderer を変更するにはさまざまな方法があります。 たとえばレンダリングするビュースクリプトを別のものに変更したり ビュースクリプトパスの置換可能な要素(サフィックスを含む) を置換する内容を指定したり、使用するレスポンスセグメントを選択したりなどのことができます。 規約どおりのディレクトリ構造以外を使用する場合は、 ViewRenderer でのパスの決定方法を変更することもできます。
ErrorHandler
および ViewRenderer
は今やコア機能として組み込まれているので、
既存のコードについてもできるだけこれに適合するようにすることをお勧めします。
0.9.3 では アクションヘルパー が利用できるようになりました。この変更にともない、以下のメソッドが削除され、 リダイレクタ アクションヘルパー に組み込まれました。
setRedirectCode()
の代わりに
Zend_Controller_Action_Helper_Redirector::setCode()
を使用します。
setRedirectPrependBase()
の代わりに
Zend_Controller_Action_Helper_Redirector::setPrependBase()
を使用します。
setRedirectExit()
の代わりに
Zend_Controller_Action_Helper_Redirector::setExit()
を使用します。
ヘルパーオブジェクトの取得方法や操作方法についての詳細は アクションヘルパーのドキュメント を、 そしてリダイレクトの設定方法(新しいメソッドなど)についての詳細は リダイレクタ アクションヘルパーのドキュメント を参照ください。
前回変更された、もっとも基本的な MVC コンポーネントの使用法は、そのまま同じです。
require_once 'Zend/Controller/Front.php'; Zend_Controller_Front::run('/path/to/controllers');
しかし、ディレクトリ構造を見直し、いくつかのコンポーネントが削除されました。 また、名前が変更されたり新たに追加されたものもあります。以下にそれらをまとめます。
Zend_Controller_Router
は削除されました。
かわりに rewrite ルータを使用してください。
Zend_Controller_RewriteRouter
は
Zend_Controller_Router_Rewrite
という名前に変わり、
このフレームワークの標準ルータに格上げされました。
Zend_Controller_Front
は、
特に別のルータを指定しない限りこのルータをデフォルトで使用します。
rewrite ルータで使用する、新しいルートクラスが追加されました。名前は
Zend_Controller_Router_Route_Module
です。
これは MVC で使用するデフォルトのルートのほかに、コントローラモジュール
をサポートしています。
Zend_Controller_Router_StaticRoute
は
Zend_Controller_Router_Route_Static
という名前に変わりました。
Zend_Controller_Dispatcher
は
Zend_Controller_Dispatcher_Standard
という名前に変わりました。
Zend_Controller_Action::_forward()
の引数が変わりました。
新しいシグネチャは次のとおりです。
final protected function _forward($action, $controller = null, $module = null, array $params = null);
$action
は常に必須です。
コントローラを指定しなかった場合は、
現在のコントローラ内のアクションであるとみなされます。
$controller
を指定しなかった場合は、
$module
は常に無視されます。
最後に、$params
で指定した任意の値が
リクエストオブジェクトに追加されます。
コントローラやモジュールは不要だがパラメータは渡したいという場合は、
コントローラやモジュールに null を指定します。
MVC コンポーネントの基本的な部分は変わっていません。 次のいずれの方法も使用可能です。
require_once 'Zend/Controller/Front.php'; Zend_Controller_Front::run('/path/to/controllers');
/* -- ルータを作成します -- */ $router = new Zend_Controller_RewriteRouter(); $router->addRoute('user', 'user/:username', array('controller' => 'user', 'action' => 'info')); /* -- ルータをコントローラに設定します -- */ $ctrl = Zend_Controller_Front::getInstance(); $ctrl->setRouter($router); /* -- コントローラのディレクトリを設定し、ディスパッチします -- */ $ctrl->setControllerDirectory('/path/to/controllers'); $ctrl->dispatch();
レスポンスオブジェクトを使用して、コンテンツとヘッダを取得することを推奨します。
これにより、アプリケーション内で
より柔軟な出力書式の切り替え (たとえば XHTML ではなく
JSON や XML を使用するなど) ができるようになります。
デフォルトでは、dispatch()
はレスポンスのレンダリングを行い、
ヘッダとレンダリングされた内容の両方を送信します。
フロントコントローラから returnResponse()
を使用してレスポンスを返し、レスポンスのレンダリングを独自に行うこともできます。
将来のバージョンのフロントコントローラでは、
レスポンスオブジェクトに出力バッファリングを使用する予定です。
これまでの API に加え、多くの機能が追加されています。 追加された機能についてはドキュメントを参照ください。
最大の変更点は、多くのコンポーネントで サブクラス化による拡張が可能になったことです。以下にポイントを整理します。
Zend_Controller_Front::dispatch()
は、デフォルトでレスポンスオブジェクトの例外をトラップします。
例外の内容はレンダリングしません。これにより、
システムについての機密情報がレンダリングされてしまうことを防ぎます。
この挙動を変更するにはいくつかの方法があります。
フロントコントローラで throwExceptions()
を設定します。
$front->throwExceptions(true);
レスポンスオブジェクトで renderExceptions()
を設定します。
$response->renderExceptions(true); $front->setResponse($response); $front->dispatch(); // あるいは $front->returnResponse(true); $response = $front->dispatch(); $response->renderExceptions(true); echo $response;
Zend_Controller_Dispatcher_Interface::dispatch()
は、ディスパッチャトークンではなく
項7.4. 「リクエストオブジェクト」
オブジェクトを使用するようになりました。
Zend_Controller_Router_Interface::route()
は、ディスパッチャトークンではなく
項7.4. 「リクエストオブジェクト」
オブジェクトを使用するようになりました。
Zend_Controller_Action
の変更点は以下のようになります。
コンストラクタが受け付ける引数は
Zend_Controller_Request_Abstract $request
、
Zend_Controller_Response_Abstract $response
および array $params (optional)
の三つになりました。
Zend_Controller_Action::__construct()
は、これらを使用してリクエストやレスポンス、
そしてオブジェクトの invokeArgs プロパティを指定します。
コンストラクタをオーバーライドすることで、
この挙動をお望みのように変更することができます。
さらによいことに、init()
メソッドを使用してインスタンスの設定を自由に行うことができます。
このメソッドは、コンストラクタでの処理の最後にコールされます。
run()
は final メソッドではなくなりました。
しかし、このメソッドはもはやフロントコントローラでは使用されません。
これは、クラスをページコントローラとして使用する場合にのみ使用します。
オプションの引数
Zend_Controller_Request_Abstract $request
および Zend_Controller_Response_Abstract $response
を受け取ります。
indexAction()
を定義する必要はなくなりました。
しかし、デフォルトのアクションとして定義しておくことを推奨します。
これにより、RewriteRouter とアクションコントローラで
デフォルトのアクションメソッドを別々に指定できるようになります。
__call()
をオーバーライドして、
未定義のアクションが自動的に処理されるようにする必要があります。
_redirect()
にはオプションで二番目、三番目の引数が追加されました。
二番目の引数はリダイレクト時に返す HTTP コードです。
三番目の引数 $prependBase
を使用すると、リクエストオブジェクトに登録したベース URL
を URL の前に連結することを指示できます。
プロパティ _action
は設定されなくなりました。
このプロパティの内容は Zend_Controller_Dispatcher_Token
でしたが、これは現在のバージョンにはもう存在しません。
トークンの唯一の目的は、要求されたコントローラやアクション、
URL パラメータについての情報を提供することでした。
これらは現在はリクエストオブジェクトから次のようにして取得できるようになっています。
// 要求されたコントローラ名を取得します。 // その際には $this->_action->getControllerName() を使用します。 // 以下の例では getRequest() を使用していますが、直接 $_request プロパティに // アクセスしてもかまいません。ただ getRequest() を使用することを推奨します。 // とういのは、親クラスがこのメソッドをオーバーライドして挙動を変更しているかもしれないからです。 $controller = $this->getRequest()->getControllerName(); // 要求されたアクション名を取得します。 // その際には $this->_action->getActionName() を使用します。 $action = $this->getRequest()->getActionName(); // リクエストパラメータを取得します。 // これは変わっていません。_getParams() メソッドおよび _getParam() メソッドは // 現在は単なるリクエストオブジェクトへのプロキシです。 $params = $this->_getParams(); $foo = $this->_getParam('foo', 'default'); // パラメータ 'foo' を取得します。見つからなかった場合は // デフォルト値 'default' を設定します。
noRouteAction()
は削除されました。
存在しないアクションメソッドを扱うには、
__call()
を使用してデフォルトのアクションに誘導します。
public function __call($method, $args) { // 存在しない 'Action' メソッドが要求された場合に、 // それをデフォルトのアクションに渡します。 if ('Action' == substr($method, -6)) { return $this->defaultAction(); } throw new Zend_Controller_Exception('無効なメソッド呼び出しです'); }
Zend_Controller_RewriteRouter::setRewriteBase()
は削除されました。かわりに
Zend_Controller_Front::setBaseUrl()
を使用してください
(あるいは、リクエストクラスを使用している場合は
Zend_Controller_Request_Http::setBaseUrl() を使用します)。
Zend_Controller_Plugin_Interface
は
Zend_Controller_Plugin_Abstract
に置き換えられました。
すべてのメソッドは、ディスパッチャトークンではなく
項7.4. 「リクエストオブジェクト」
をやり取りするようになりました。