WEBアプリケーション研究室 開発ノート TOP

WEBアプリケーション研究室 開発ノート Zend Framwork

スポンサーサイト

-------- --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

    このエントリーをはてなブックマークに追加

Zend_Controllerを使用してコマンドラインから実行するCLIプログラムを作ってます。例外処理で、ディスパッチループに入る前に例外を投げた場合ErrorHandlerには行きません。デフォルトでは例外はResponseにためられて、何も出力しない設定になっているので何も表示されません。
Front_Controllerで


require_once 'Zend/Controller/Front.php';
$front = Zend_Controller_Front::getInstance();
$front->throwExceptions(true);
としてやれば例外をためないで投げるようになりますが、今度はErrorHandlerも無視されてしまうので404の処理なども独自に実装しなければならず面倒です。

$front->getResponse()->renderExceptions(true);
で、Responseにためた例外を出力するように出来ますが、私はset_exception_handlerを利用して自分が見やすいように例外を表示するようにしてあるので、Action内の例外はErrorHandlerに、それ以外は投げるようにしたいと思いました。Responseを拡張しても出来そうですがクラス階層が微妙になるので$front->dispatch()直後に次のような処理を入れて対応しました。

$front->dispatch();
if(!$front->getRequest()->isDispatched())
{
$e = $front->getResponse()->getException();
if($e)
{
throw $e[0];
}
}

    このエントリーをはてなブックマークに追加

Zend_Controllerではエラーハンドラを設定しておくとAction内で発生した例外及びコントローラーやアクションが見つからなかった場合の処理を一つのアクションに全部集めて処理ができます。

注意が必要なのはアクション内でもinit()で投げる時は注意が必要です。Zend_Controller_Actionを継承したMyControllerActionを作って重複コードを集め、全てのActionはそいつから派生させようという場合ErrorControllerも同じコントローラーから派生させるとうまくいかなくなります。


class MyControllerAction extends Zend_Controller_Action
{
public function init()
{
trown new Exception('error!!');
}




class Cli_ErrorController extends MyControllerAction
{
public function indexAction()
{



こうするとディスパッチループの中で最初のコントローラーをnewした時とエラーコントローラーをnewした時、2回同じ例外が投げられることになります。このままだと無限ループになってしまうのでZend_Controller_Plugin_ErrorHandlerでは2度目の例外はそのまま投げるようにしています。

if ($this->_isInsideErrorHandlerLoop) {
$exceptions = $response->getException();
if (count($exceptions) > $this->_exceptionCountAtFirstEncounter) {
// Exception thrown by error handler; tell the front controller to throw it
$frontController->throwExceptions(true);
throw array_pop($exceptions);
}
}
エラーハンドラにかかわらずアクションの親クラスのinit()は2度呼ばれる可能性があるので注意が必要だと思います。

    このエントリーをはてなブックマークに追加

久々にZend Framworkをいじる機会があって、忘れていたのですが
ルートの設定で、symfonyは最初にマッチしたルートが採用されるのに対して、Zend Framworkは最後にマッチしたルートが採用されます。

だから汎用的なルートはsymfonyの場合は最後のほうに書いて、Zend Framworkは最初のほうに書かないとだめです。

個人的な感覚の問題かもしれないけどsymfonyの方が直感的な気がします。

    このエントリーをはてなブックマークに追加
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。