Zend Framework の紹介

 Learning Zend Framework

appendix

 Zend Framework リファレンス


  • 第36章 Zend_Gdata
  • 第37章 Zend_Http
  • 第38章 Zend_InfoCard
  • 第39章 Zend_Json
  • 第40章 Zend_Layout
  • 第41章 Zend_Ldap
  • 第42章 Zend_Loader
  • 第43章 Zend_Locale
  • 第44章 Zend_Log
  • 第45章 Zend_Mail
  • 第46章 Zend_Markup
  • 第47章 Zend_Measure
  • 第48章 Zend_Memory
  • 第49章 Zend_Mime
  • 第50章 Zend_Navigation
  • 第51章 Zend_Oauth
  • 第52章 Zend_OpenId
  • 第53章 Zend_Paginator
  • 第54章 Zend_Pdf
  • 第55章 Zend_ProgressBar
  • 第56章 Zend_Queue
  • 第57章 Zend_Reflection
  • 第58章 Zend_Registry
  • 第59章 Zend_Rest

  • 第60章 Zend_Search_Lucene
  • 第61章 Zend_Serializer
  • 第62章 Zend_Server
  • 第63章 Zend_Service
  • 第64章 Zend_Session
  • 第65章 Zend_Soap
  • 第66章 Zend_Tag
  • 第67章 Zend_Test
  • 第68章 Zend_Text
  • 第69章 Zend_TimeSync
  • 第70章 Zend_Tool
  • 第71章 Zend_Tool_Framework
  • 第72章 Zend_Tool_Project
  • 第73章 Zend_Translate
  • 第74章 Zend_Uri
  • 第75章 Zend_Validate
  • 第76章 Zend_Version
  • 第77章 Zend_View
  • 第78章 Zend_Wildfire
  • 第79章 Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery
  • Translation 70.6% Update 2010-11-28 - Revision 23415

    24.10. プラグイン

    24.10.1. 導入

    コントローラにはプラグイン機構が組み込まれており、 コントローラの処理中にイベントが発生した際にユーザのコードをコールできます。 フロントコントローラは、プラグインブローカにユーザのプラグインを登録します。 そして、イベントメソッドがコールされた際に、 フロントコントローラに登録されているプラグインをプラグインブローカが実行します。

    イベントメソッドは、抽象クラス Zend_Controller_Plugin_Abstract で定義されています。 ユーザが作成するプラグインクラスは、これを継承させます。

    • routeStartup() は、Zend_Controller_Frontルータ をコールしてルートに対するリクエストの評価を始める前にコールされます。

    • routeShutdown() は、 ルータ がリクエストのルーティングを終了した後にコールされます。

    • dispatchLoopStartup() は、Zend_Controller_Front がディスパッチループに入る前にコールされます。

    • preDispatch() は、アクションが ディスパッチャ でディスパッチされる前にコールされます。 このコールバックは、プロキシやフィルタ的な動作をさせることができます。 リクエストの内容を変更してディスパッチフラグをリセット (Zend_Controller_Request_Abstract::setDispatched(false) を使用します) することで、現在のアクションをスキップさせたり置き換えたりできます。

    • postDispatch() は、アクションが ディスパッチャ でディスパッチされた後にコールされます。 このコールバックは、プロキシやフィルタ的な動作をさせることができます。 リクエストの内容を変更してディスパッチフラグをリセット (Zend_Controller_Request_Abstract::setDispatched(false) を使用します) することで、新しいディスパッチ先アクションを指定できます。

    • dispatchLoopShutdown() は、Zend_Controller_Front がディスパッチループを抜けた後にコールされます。

    24.10.2. プラグインの書き方

    プラグインクラスを書くには、単に抽象クラス Zend_Controller_Plugin_Abstract をインクルードしてそれを継承するだけです。

    class MyPlugin extends Zend_Controller_Plugin_Abstract
    {
        
    // ...
    }

    Zend_Controller_Plugin_Abstract には抽象メソッドはありません。 つまり、上に示したイベントメソッドを、 プラグインクラスでかならず実装しなければならないわけではありません。 プラグインの作者が、必要なものだけを選んで実装できます。

    Zend_Controller_Plugin_Abstract では、 リクエストオブジェクトやレスポンスオブジェクトをプラグインから操作できます。 それぞれ、getRequest() メソッドおよび getResponse() メソッドを使用します。

    24.10.3. プラグインの使用法

    プラグインクラスを登録するには、 Zend_Controller_Front::registerPlugin() をコールします。 これは、いつでも行うことができます。 次の例は、コントローラチェインでプラグインを使用する方法を示すものです。

    class MyPlugin extends Zend_Controller_Plugin_Abstract
    {
        public function 
    routeStartup(Zend_Controller_Request_Abstract $request)
        {
            
    $this->getResponse()
                 ->
    appendBody("<p>routeStartup() がコールされました</p>\n");
        }

        public function 
    routeShutdown(Zend_Controller_Request_Abstract $request)
        {
            
    $this->getResponse()
                 ->
    appendBody("<p>routeShutdown() がコールされました</p>\n");
        }

        public function 
    dispatchLoopStartup(
            
    Zend_Controller_Request_Abstract $request)
        {
            
    $this->getResponse()
                 ->
    appendBody("<p>dispatchLoopStartup() がコールされました</p>\n");
        }

        public function 
    preDispatch(Zend_Controller_Request_Abstract $request)
        {
            
    $this->getResponse()
                 ->
    appendBody("<p>preDispatch() がコールされました</p>\n");
        }

        public function 
    postDispatch(Zend_Controller_Request_Abstract $request)
        {
            
    $this->getResponse()
                 ->
    appendBody("<p>postDispatch() がコールされました</p>\n");
        }

        public function 
    dispatchLoopShutdown()
        {
            
    $this->getResponse()
                 ->
    appendBody("<p>dispatchLoopShutdown() がコールされました</p>\n");
        }
    }

    $front Zend_Controller_Front::getInstance();
    $front->setControllerDirectory('/path/to/controllers')
          ->
    setRouter(new Zend_Controller_Router_Rewrite())
          ->
    registerPlugin(new MyPlugin());
    $front->dispatch();

    他に何かの出力を行うアクションがなく、ひとつのアクションのみがコールされたとしましょう。 上のプラグインは、次のような出力を行います。

    <p>routeStartup() がコールされました</p>
    <
    p>routeShutdown() がコールされました</p>
    <
    p>dispatchLoopStartup() がコールされました</p>
    <
    p>preDispatch() がコールされました</p>
    <
    p>postDispatch() がコールされました</p>
    <
    p>dispatchLoopShutdown() がコールされました</p>
    [注意] 注意

    プラグインは、フロントコントローラの実行時ならいつでも登録できます。 しかし、プラグインがイベントメソッドを登録しようとしているイベントが終わった後では、 そのメソッドは実行されません。

    24.10.4. プラグインの取得と操作

    時には、プラグインの登録を解除したりプラグインの情報を取得したいこともあるでしょう。 フロントコントローラには、そのような場合のために次のメソッドが用意されています。

    • getPlugin($class) は、指定したクラス名のプラグインを取得します。 一致するプラグインがない場合は FALSE を返します。 同じクラス名のプラグインが複数登録されている場合は、結果を配列で返します。

    • getPlugins() は、プラグインスタック全体を取得します。

    • unregisterPlugin($plugin) は、プラグインをスタックから登録解除します。 パラメータには、プラグインオブジェクト自体かそのクラス名を渡します。 クラス名を渡すと、一致するプラグインがすべて削除されます。

    24.10.5. 標準の配布パッケージに含まれるプラグイン

    Zend Framework の配布パッケージには、 エラー処理用のプラグインが標準で組み込まれています。

    24.10.5.1. ActionStack

    ActionStack プラグインは、リクエストをスタックで管理します。 postDispatch プラグインとして動作します。 現在のリクエストオブジェクトで既に転送先が指定されている (別のアクションがコールされている) 場合は、何も行いません。 転送されていない場合はスタックの最上位の要素を取り出し、 そのリクエストが指すアクションに転送します。 スタックの処理は LIFO (後入れ先出し) 方式で行います。

    このプラグインをフロントコントローラから取得するには、 Zend_Controller_Front::getPlugin('Zend_Controller_Plugin_ActionStack') とします。プラグインオブジェクトを取得したら、 さまざまな仕組みを利用できるようになります。

    • getRegistry() および setRegistry()ActionStack は、内部的に Zend_Registry のインスタンスを使ってスタックを管理しています。 別のレジストリインスタンスでこれを置き換えたり、 インスタンスを取得したりする際にこれらのアクセサを使用します。

    • getRegistryKey() および setRegistryKey()。 これらは、スタックに格納する際にレジストリのどのキーを使用するかを指定します。 デフォルト値は 'Zend_Controller_Plugin_ActionStack' です。

    • getStack() は、 そのアクションのスタック全体を取得します。

    • pushStack() および popStack() は、それぞれスタックへの追加とスタックからの取り出しを行います。 pushStack() にはリクエストオブジェクトを渡します。

    さらに forward() メソッドが存在します。 このメソッドにはリクエストオブジェクトを渡し、 フロントコントローラにおける現在のリクエストオブジェクトの状態を ここで渡したオブジェクトの状態に設定します。 そして、リクエストを未ディスパッチ状態に戻します (ディスパッチループの次の処理に強制的に進ませます)。

    24.10.5.2. Zend_Controller_Plugin_ErrorHandler

    Zend_Controller_Plugin_ErrorHandler は、アプリケーションからスローされた例外を処理するためのプラグインです。 たとえば、指定したコントローラやアクションが見つからないといったエラーを処理します。 これは、MVC の例外についてのセクション で説明したメソッド群の代わりとして使用できます。

    このプラグインが主に対象としているのは、次のような例外です。

    • 一致したルートが見つからない場合に発生する例外

    • コントローラやアクションメソッドが見つからない場合に発生する例外

    • アクションコントローラ内で発生する例外

    言い換えると、ErrorHandler プラグインが想定しているのは、HTTP 404 型のエラー (ページが存在しない) と 500 型のエラー (内部エラー) ということになります。 他のプラグインで発生した例外の処理は、想定していません。

    デフォルトでは、Zend_Controller_Plugin_ErrorHandler はデフォルトモジュールの ErrorController::errorAction() に処理を転送します。これを変更するには、以下のようなアクセス用メソッドを使用します。

    • setErrorHandlerModule() は、 使用するコントローラモジュール名を設定します。

    • setErrorHandlerController() は、 使用するコントローラを設定します。

    • setErrorHandlerAction() は、 使用するコントローラアクションを設定します。

    • setErrorHandler() は連想配列を受け取ります。 この連想配列のキーには 'module'、'controller' あるいは 'action' を指定することができ、 それぞれ対応する値を設定します。

    さらに、コンストラクタの引数として連想配列を渡すこともできます。 この場合、その配列がそのまま setErrorHandler() に渡されます。

    Zend_Controller_Plugin_ErrorHandlerpostDispatch() フックとして登録され、 レスポンスオブジェクト に格納された例外を確認します。もし何かの例外が見つかったら、 事前に登録されているエラーハンドラアクションに処理を転送します。

    エラーハンドラへのディスパッチ中に例外が発生した場合は、 このプラグインはフロントコントローラに例外をスローします。 その際に、レスポンスオブジェクトに格納された直近の例外を再度スローします。

    24.10.5.2.1. 404 ハンドラとしての ErrorHandler の使用

    ErrorHandler プラグインが捕捉するのは、 アプリケーションのエラーだけではありません。 コントローラチェインが次のコントローラクラスやアクションメソッドを 見つけられなかった場合に、404 ハンドラとして動作させることもできます。 そのためには、エラーコントローラ内で例外の型を調べる必要があります。

    捕捉した例外は、リクエストで登録したオブジェクトの中に記録されます。 これを取得するには、 Zend_Controller_Action::_getParam('error_handler') を使用します。

    class ErrorController extends Zend_Controller_Action
    {
        public function 
    errorAction()
        {
            
    $errors $this->_getParam('error_handler');
        }
    }

    エラーオブジェクトを取得したら、次に $errors->type でその型を調べます。 これは、次のいずれかとなります。

    • Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE は、一致したルートが見つからなかったことを表します。

    • Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER は、コントローラが見つからなかったことを表します。

    • Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION は、アクションが見つからなかったことを表します。

    • Zend_Controller_Plugin_ErrorHandler::EXCEPTION_OTHER は、その他の例外を表します。

    最初の3つの型であった場合に、404 ページを返せばいいわけです。

    class ErrorController extends Zend_Controller_Action
    {
        public function 
    errorAction()
        {
            
    $errors $this->_getParam('error_handler');

            switch (
    $errors->type) {
                case 
    Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
                case 
    Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
                case 
    Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
                    
    // 404 エラー -- コントローラあるいはアクションが見つかりません
                    
    $this->getResponse()
                         ->
    setRawHeader('HTTP/1.1 404 Not Found');

                    
    // ... 何か、表示する内容を作成します ...
                    
    break;
                default:
                    
    // アプリケーションのエラー。エラーページを表示しますが、
                    // ステータスコードは変更しません
                    
    break;
            }
        }
    }

    エラーハンドラで発生した礼儀を取得するには、 error_handler オブジェクトのプロパティ exception を使用します。

    public function errorAction()
    {
            
    $errors $this->_getParam('error_handler');

            switch (
    $errors->type) {
                case 
    Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
                case 
    Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
                case 
    Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
                    
    // 404 エラー -- コントローラあるいはアクションが見つかりません
                    
    $this->getResponse()
                         ->
    setRawHeader('HTTP/1.1 404 Not Found');

                    
    // ... 何か、表示する内容を作成します ...
                    
    break;
                default:
                    
    // アプリケーションのエラー。エラーページを表示しますが、
                    // ステータスコードは変更しません

                    // ...

                    // 例外をログに記録します
                    
    $exception $errors->exception;
                    
    $log = new Zend_Log(
                        new 
    Zend_Log_Writer_Stream(
                            
    '/tmp/applicationException.log'
                        
    )
                    );
                    
    $log->debug($exception->getMessage() . "\n" .
                                
    $exception->getTraceAsString());
                    break;
            }
    }
    24.10.5.2.2. 前回のレンダリング結果の扱い

    ひとつのリクエストで複数のアクションにディスパッチする場合、 あるいはアクション内で render() を複数回コールする場合などは、 レスポンスオブジェクト内にすでに内容が格納されていることがあります。 これをうまく処理しないと、本当に必要な内容と それ以外の内容が混じってしまう恐れがあります。

    そのような場合にページの中でエラー処理をしたい場合は、 特に何も手を加える必要はありません。 そのような内容をレンダリングしたくないという場合は、 ビューのレンダリング前に以前の内容を消去しておく必要があります。

    $this->getResponse()->clearBody();
    24.10.5.2.3. プラグインの使用例

    例 24.16. 標準的な使用法

    $front Zend_Controller_Front::getInstance();
    $front->registerPlugin(new Zend_Controller_Plugin_ErrorHandler());

    例 24.17. 別のエラーハンドラの設定

    $front Zend_Controller_Front::getInstance();
    $front->registerPlugin(new Zend_Controller_Plugin_ErrorHandler(array(
        
    'module'     => 'mystuff',
        
    'controller' => 'static',
        
    'action'     => 'error'
    )));

    例 24.18. アクセス用メソッドの使用

    $plugin = new Zend_Controller_Plugin_ErrorHandler();
    $plugin->setErrorHandlerModule('mystuff')
           ->
    setErrorHandlerController('static')
           ->
    setErrorHandlerAction('error');

    $front Zend_Controller_Front::getInstance();
    $front->registerPlugin($plugin);

    24.10.5.2.4. エラーコントローラの例

    エラーハンドラプラグインを使用するには、 エラーコントローラが必要です。以下にシンプルな例を示します。

    class ErrorController extends Zend_Controller_Action
    {
        public function 
    errorAction()
        {
            
    $errors $this->_getParam('error_handler');

            switch (
    $errors->type) {
                case 
    Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
                case 
    Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
                case 
    Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
                    
    // 404 エラー -- コントローラあるいはアクションが見つかりません
                    
    $this->getResponse()->setRawHeader('HTTP/1.1 404 Not Found');

                    
    $content =<<<EOH
    <h1>エラー!</h1>
    <p>そのページは存在しません。</p>
    EOH;
                    break;
                default:
                    
    // アプリケーションのエラー
                    
    $content =<<<EOH
    <h1>エラー!</h1>
    <p>予期せぬエラーが発生しました。後でもう一度お試しください。</p>
    EOH;
                    break;
            }

            
    // 前回の内容を消去します
            
    $this->getResponse()->clearBody();

            
    $this->view->content $content;
        }
    }

    24.10.5.3. Zend_Controller_Plugin_PutHandler

    Zend_Controller_Plugin_PutHandlerは、 まるで POST リクエスト・ボディのようなリクエスト・パラメータに PUT リクエスト・ボディを配置するために、 ドロップイン・プラグインを提供します。 それはリクエストを調べます、そして、 PUT ならば、 生の PUT ボディを解析してリクエストに配置されるパラメータの配列にするためにparse_strを使います。 例えば、

    PUT /notes/5.xml HTTP/1.1

    title
    =Hello&amp;body=World

    'title' 及び 'body' パラメータを通常のリクエスト・パラメータとして受け取るために、 プラグインを登録します:

    $front Zend_Controller_Front::getInstance();
    $front->registerPlugin(new Zend_Controller_Plugin_PutHandler());

    そして、コントローラ内でリクエストから PUT ボディー・パラメータに名前によるアクセスができます:

    ...
    public function 
    putAction()
    {
        
    $title $this->getRequest()->getParam('title'); // $title = "Hello"
        
    $body $this->getRequest()->getParam('body'); // $body = "World"
    }
    ...
    digg delicious meneame google twitter technorati facebook

    Comments

    Loading...