7.8. アクションヘルパー

7.8.1. 導入

アクションヘルパーを使用すると、Zend_Controller_Action を継承した任意のアクションコントローラに対して 実行時やその他必要に応じて機能追加をすることができます。 アクションヘルパーの狙いは、 アクションコントローラに共通機能を追加するために いちいち抽象クラスを継承する手間を省くことにあります。

アクションヘルパーにはさまざまな使用法があります。 たとえば、Zend_View_HelpersZend_Controller_Plugin と同じように、処理の仲買をするために用いることもできます。 アクションヘルパーは (Zend_View_Helpers と同様に)、 必要になった時点で読み込むこともできますし、 リクエスト時 (起動時) やアクションコントローラの作成時 (init()) で読み込むこともできます。詳細は、以下の使用例を参照ください。

7.8.2. ヘルパーの初期化

ヘルパーを初期化するにはいくつかの方法があります。 必要に応じて、またそのヘルパーの機能に応じて使い分けましょう。

ヘルパーブローカは、Zend_Controller_Action$_helper に格納されます。 このブローカを使用して、ヘルパーを取得したりコールしたりします。 以下のような方法があります。

  • 明示的に getHelper() を使用します。 ヘルパーの名前を指定すると、 そのヘルパーオブジェクトが返されます。

    <?php
    $flashMessenger = $this->_helper->getHelper('FlashMessenger');
    $flashMessenger->addMessage('We did something in the last request');
    
  • ヘルパーブローカの __get() 機能を使用すると、 まるでブローカのプロパティであるかのようにヘルパーを操作できます。

    <?php
    $flashMessenger = $this->_helper->FlashMessenger;
    $flashMessenger->addMessage('We did something in the last request');
    
  • たいていのアクションヘルパーは direct() メソッドを実装しており、 これはそのヘルパーのデフォルトメソッドをコールします。 FlashMessenger の例では、 addMessage() をコールします。

    <?php
    $this->_helper->FlashMessenger('We did something in the last request');
    
[注意] 注意

これらの例は、すべて同じことを行っています。

ヘルパーのインスタンスを明示的に作成したいと考えるかもしれません。 たとえばアクションコントローラ以外からヘルパーを使用したいだとか、 すべてのアクションのヘルパーブローカに同じヘルパーを渡したいだとかいった場合です。 インスタンスを作成する方法は、通常の PHP のクラスと同じです。

7.8.3. ヘルパーブローカ

Zend_Controller_Action_HelperBroker がヘルパーオブジェクトやそのパスの登録に関する詳細を処理します。 また、必要に応じてそこからヘルパーを取得することができます。

ヘルパーをブローカに登録するには addHelper を使用します。

<?php
Zend_Controller_Action_HelperBroker::addHelper($helper);

もちろん、ヘルパーのインスタンスを作成してそれをブローカに渡すという作業は 時間とリソースを消費します。これらの作業の手間をほんの少し省くためのメソッドとして、 addPrefix()addPath() が用意されています。

  • addPrefix() はクラスのプレフィックスを受け取り、 それをもとにヘルパークラスのパスを決定します。 プレフィックスが、Zend Framework のクラス命名規約に沿っているものとみなして、 パスを決定します。

    <?php
    // My/Action/Helpers/ にある、名前が My_Action_Helpers で始まるヘルパーを追加します
    Zend_Controller_Action_HelperBroker::addPrefix('My_Action_Helpers');
    
  • addPath() は、最初の引数にディレクトリ、 そして二番目の引数にクラスのプレフィックス (デフォルトは 'Zend_Controller_Action_Helper') を指定します。 これは、指定したディレクトリにある指定したプレフィックスのクラスを追加します。

    <?php
    // Plugins/Helpers/ にある、名前が Helper で始まるヘルパーを追加します
    Zend_Controller_Action_HelperBroker::addPath('./Plugins/Helpers', 'Helper');
    

これらは静的メソッドなので、コントローラチェイン内の任意の場所で使用することができます。 これにより、必要に応じて動的にヘルパーを追加できることになります。

ヘルパークラスがヘルパーブローカ内に存在するかどうかを調べるには hasHelper($name) を使用します。$name には、ヘルパーのショートネーム (プレフィックスを除いたもの) を指定します。

<?php
// 'redirector' ヘルパーがブローカに登録されているかどうかを調べます
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
    echo 'Redirector helper registered
}

最後に、登録済みのヘルパーをブローカから削除するには removeHelper($name) を使用します。$name には、ヘルパーのショートネーム (プレフィックスを除いたもの) を指定します。

<?php
// 'redirector' ヘルパーがブローカに登録されている場合にはそれを削除します
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
    Zend_Controller_Action_HelperBroker::removeHelper('redirector')
}

7.8.4. 組み込みのアクションヘルパー

Zend Framework には、デフォルトで二種類のアクションヘルパーが組み込まれています。 セッション単位のフラッシュメッセージを扱う FlashMessenger と、 アプリケーション内から内部あるいは外部へのリダイレクトを実装できるようにする Redirector です。

7.8.4.1. FlashMessenger

7.8.4.1.1. 導入

FlashMessenger ヘルパーは、 次のリクエストの際にユーザに見せる必要のあるメッセージを渡すためのものです。 この機能を実現するため、FlashMessengerZend_Session_Namespace を使用してメッセージを保管しています。 Zend_SessionZend_Session_Namespace を使用する際には、起動ファイル中で Zend_Session::start() を実行するようにしましょう (詳細な使用例は Zend Session を参照ください)。

7.8.4.1.2. 基本的な使用例

以下の使用例は、もっとも基本的なフラッシュメッセンジャーの使用法を示すものです。 アクション /some/my がコールされると、フラッシュメッセージに "Record Saved!" が保存されます。そして、その次のアクション /some/my-next-request へのリクエストの際にそれを取得 (そして削除) します。

<?php
class SomeController extends Zend_Controller_Action
{
    /**
     * FlashMessenger
     *
     * @var Zend_Controller_Action_Helper_FlashMessenger
     */
    protected $_flashMessenger = null;
    
    
    public function init()
    {
        $this->_flashMessenger = $this->_helper->getHelper('FlashMessenger');
        $this->initView();
    }
    
    public function myAction()
    {
        /**
         * Zend_Controller_Action_Helper_FlashMessenger
         * のインスタンスを必要に応じて取得するためのデフォルトメソッド
         */
        $this->_flashMessenger->addMessage('Record Saved!');
    }

    public function myNextRequestAction()
    {
        $this->view->messages = $this->_flashMessenger->getMessages();
        $this->render();
    }
}

7.8.4.2. Redirector

7.8.4.2.1. 導入

Redirector ヘルパーは、 アプリケーション内で必要となるリダイレクト処理用のオブジェクトとして使用します。 _redirect() メソッドと比べた場合の利点としては、 サイト全体で使用する設定を事前に組み込んでおけることがあります。また、 Zend_Controller_Action::_forward() の場合と同様に、組み込みのインターフェイス goto($action, $controller, $module, $params) が使用できることも利点となります。

Redirector では、 リダイレクトの設定を行うメソッドとして次のようなものが用意されています。

  • setCode() を使用して、 リダイレクトの際に使用する HTTP レスポンスコードを設定します。

  • setExit() を使用して、 リダイレクトの後で強制的に exit() を実行させるようにします。 デフォルトは true です。

  • setGoto() を使用して、goto() に何も渡されなかったときのデフォルトの URL を設定します。 Zend_Controller_Action::_forward() の API である setgoto($action, $controller = null, $module = null, array $params = array()); を使用します。

  • setGotoRoute() を使用して、 登録済みのルートにもとづいた URL を設定します。 キー/値 のペアの配列とルート名を渡し、 それをもとにルートの型と定義から URL を作成します。

  • setGotoUrl() を使用して、gotoUrl() に何も渡されなかったときのデフォルトの URL を設定します。 URL を表す文字列を受け取ります。

  • setPrependBase() を使用して、 setGotoUrl()gotoUrl() あるいは gotoUrlAndExit() で指定した URL の前にリクエストのベース URL を追加します。

さらに、実際のリダイレクトを行うためのメソッドとして以下のものが用意されています。

  • goto() は、setGoto() (_forward() 風の API) を用いて作成した URL にリダイレクトします。

  • gotoRoute() は、setGotoRoute() (ルートの作成) を用いて作成した URL にリダイレクトします。

  • gotoUrl()setGotoUrl() (URL 文字列の指定) を用いて作成した URL にリダイレクトします。

リダイレクト先の URL を知るには getRedirectUrl() を使用します。 これはいつでも使用できます。

7.8.4.2.2. 基本的な使用例

例 7.1. オプションの設定

この例ではデフォルトのオプションを少し変更します。 HTTP ステータスコードを 303 にし、リダイレクト後に exit() しないようにして、そしてリダイレクトの際のデフォルト URL を指定しています。

<?php
class SomeController extends Zend_Controller_Action
{
    /**
     * Redirector - defined for code completion
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;
    
    public function init()
    {
        $this->_redirector = $this->_helper->getHelper('Redirector');
        
        // リダイレクタのデフォルトのオプションを設定します
        // このオブジェクトはヘルパーブローカに登録されるので、
        // これ以降のすべてのアクションで有効となります
        $this->_redirector->setCode('303')
                          ->setExit(false)
                          ->setGoto("this-action", "some-controller");
    }
    
    public function myAction()
    {
        /* 何かを行います */

        // 先ほど登録した URL にリダイレクトし、その後で
        // exit() します
        $this->_redirector->redirectAndExit();
        return; // 決してここには到達しません
    }
}
?>

例 7.2. デフォルト設定の使用

この例ではデフォルト設定を使用しています。 つまり、リダイレクトするとすぐに exit() が実行されるということです。

<?php
// ALTERNATIVE EXAMPLE
class AlternativeController extends Zend_Controller_Action
{
    /**
     * Redirector - defined for code completion
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;
    
    public function init()
    {
        $this->_redirector = $this->_helper->getHelper('Redirector');
    }
    
    public function myAction()
    {
        /* 何かを行います */

        $this->_redirector->gotoUrl('/my-controller/my-action/param1/test/param2/test2');
        return; // リダイレクト後に自動的に exit() されるので、決してここには到達しません
    }
}
?>

例 7.3. goto() での _forward() API の使用

goto() の API は、 Zend_Controller_Action::_forward() と同じ形式です。違う点は、このメソッドは渡されたパラメータから URL を作成し、デフォルトルータのデフォルトフォーマットである :module/:controller/:action/* を使用するということです。 また、アクションチェインではなくリダイレクトを行います。

<?php
class ForwardController extends Zend_Controller_Action
{
    /**
     * Redirector - defined for code completion
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;
    
    public function init()
    {
        $this->_redirector = $this->_helper->getHelper('Redirector');
    }
    
    public function myAction()
    {
        /* 何かを行います */

        // 現在のモジュールの 'my-controller' コントローラの
        // 'my-action' アクションにリダイレクトします。
        // パラメータは param1 => test、param2 => test2 となります。
        $this->_redirector->goto('my-action', 'my-controller', null, array('param1' => 'test', 'param2' => 'test2'));
    }
}
?>

例 7.4. gotoRout() でのルートアセンブリの使用

次の例は、ルータassemble() メソッドを使用して、 パラメータで指定した連想配列に基づく URL を作成しています。 次のようなルートが登録されているものと仮定します。

<?php
$route = new Zend_Controller_Router_Route(
    'blog/:year/:month/:day/:id',
    array('controller' => 'archive', 'module' => 'blog', 'action' => 'view')
);
$router->addRoute('blogArchive', $route);
?>

year を 2006、month を 4、そして day を 24 として配列を渡すと、結果の URL は /blog/2006/4/24/42 となります。

<?php
class BlogAdminController extends Zend_Controller_Action
{
    /**
     * Redirector - defined for code completion
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;
    
    public function init()
    {
        $this->_redirector = $this->_helper->getHelper('Redirector');
    }
    
    public function returnAction()
    {
        /* 何かを行います */

        // blog の過去記事にリダイレクトします。URL は
        // /blog/2006/4/24/42 になります。
        $this->_redirector->gotoRoute(
            array('year' => 2006, 'month' => 4, 'day' => 24, 'id' => 42),
            'blogArchive'
        );
    }
}
?>

7.8.4.3. ViewRenderer

7.8.4.3.1. 導入

ViewRenderer ヘルパーは、 以下のような要件を満たすために作られたものです。

  • コントローラ内でいちいちビューオブジェクトのインスタンスを 作成しなくても済むようにする。 ビューオブジェクトは自動的にコントローラに登録されます。

  • ビュースクリプトやヘルパー、そしてフィルタのパスを 現在のモジュールに基づいて自動的に設定し、 モジュール名をヘルパーやフィルタのクラス名の先頭に自動的に関連付ける。

  • すべてのコントローラとアクションで使用できる グローバルなビューオブジェクトを作成する。

  • すべてのコントローラで使用する、 デフォルトのビューレンダリングオプションを設定できるようにする。

  • 何も指定しなくても、 自動的にビュースクリプトをレンダリングできる機能を追加する。

  • ビューの基底パスやビュースクリプトのパスを 独自に指定できるようにする。

[注意] 注意

_forward() やリダイレクト、あるいは手動でのレンダリングを行う場合は、 自動レンダリングは不要です。これらの処理を行う場合は、 出力を自前で行うことを ViewRenderer に対して指示します。

[注意] 注意

ViewRenderer はデフォルトで有効になっています。 これを無効にするには、フロントコントローラのパラメータ noViewRenderer を指定する ($front->setParam('noViewRenderer')) か、 あるいはヘルパーブローカからヘルパーを削除 (Zend_Controller_Action_HelperBroker::removeHelper('viewRenderer')) します。

フロントコントローラでのディスパッチ処理の前に ViewRenderer の設定を変更したい場合は、 次のいずれかの方法を使用します。

  • 独自の ViewRenderer のインスタンスを作成し、 ヘルパーブローカにそれを渡して登録する。

    <?php
    $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer();
    $viewRenderer->setView($view)
                 ->setViewSuffix('php');
    Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
    
  • フロントコントローラのインスタンスが作成された後で、 ヘルパーブローカに登録されている ViewRenderer オブジェクトを取得する。

    <?php
    $front = Zend_Controller_Front::getInstance();
    
    $viewRenderer = Zend_Controller_Action_HelperBroker::getExistingHelper('viewRenderer');
    $viewRenderer->setView($view)
                 ->setViewSuffix('php');
    
7.8.4.3.2. API

もっとも基本的な使用法は、単に ViewRenderer のインスタンスを作成してそれをヘルパーブローカに渡すというものです。

<?php
Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_ViewRenderer());

アクションコントローラのインスタンスが最初に作成されたときに、 ViewRenderer がビューオブジェクトのインスタンスを作成します。 コントローラのインスタンスが作成されるたびに、ViewRendererinit() がコールされます。 ここでアクションコントローラのビュープロパティを設定し、 現在のモジュールからの相対パスを指定して addScriptPath() をコールします。 これは現在のモジュール名に基づいたプレフィックスをクラス名の先頭につけてコールされるので、 ヘルパーやフィルタのクラスをモジュール内で効率的に管理することができます。

postDispatch() がコールされるたびに、現在のアクションの render() を自動的にコールします。

例として、次のようなクラスを考えてみましょう。

<?php
// foo モジュールのコントローラクラス
class Foo_BarController extends Zend_Controller_Action
{
    // デフォルトで bar/index.phtml をレンダリングするので、特に何もする必要はありません
    public function indexAction()
    {
    }

    // 変数 'foo' の値を 'bar' に設定して bar/populate.phtml をレンダリングします
    // ビューオブジェクトは既に preDispatch() で定義されているので、既に使用可能です
    public function populateAction()
    {
        $this->view->foo = 'bar';
    }
}
?>

// ビュースクリプトの中では、たとえば次のように書きます
<?php $this->foo(); // Foo_View_Helper_Foo::foo() をコールします ?>

ViewRenderer には、 ビューのオプションを取得したり設定したりするためのメソッドも豊富に用意されています。

  • setView($view)ViewRenderer が使用するビューオブジェクトを設定します。 これは、クラスのプロパティ $view の値を設定します。

  • setNeverRender($flag = true) を使用すると、自動レンダリング機能を全体的に (すべてのコントローラに対して)無効にしたり有効にしたりできます。 true を指定すると、そのコントローラの postDispatch() では render() をコールしなくなります。 getNeverRender() は、現在の設定を取得します。

  • setNoRender($flag = true) を使用すると、自動レンダリングを無効にしたり有効にしたりできます。 true を指定すると、現在のコントローラの postDispatch() では render() をコールしなくなります。 この設定は、preDispatch() がコールされるたびにいったんリセットされます (つまり、自動レンダリングを無効にしたいすべてのコントローラで 個々にこれを設定する必要があるということです)。 getNoRender() は、現在の設定を取得します。

  • setNoController($flag = true) を使用すると、render() がコントローラ名のサブディレクトリにあるアクションスクリプトを 読みにいかなくすることができます (デフォルトでは読みにいきます)。 getNoController() は、現在の設定を取得します。

  • setScriptAction($name) を使用すると、レンダリングするアクションスクリプトを指定することができます。 $name は、スクリプト名から拡張子を除いたもの (そして、noController が指定されていない限り、 コントローラのディレクトリ名も除いたもの) となります。 指定しなかった場合は、リクエストオブジェクト内のアクションに基づいた名前の ビュースクリプトを探します。 getScriptAction() は、現在の設定を取得します。

  • setResponseSegment($name) を使用すると、レンダリング結果を出力する レスポンスオブジェクトのセグメント名を指定することができます。 指定しなかった場合は、デフォルトのセグメントにレンダリングします。 getResponseSegment() は、現在の設定を取得します。

  • initView($path, $prefix, $options は、ビューの基底パスを指定します。 また、ヘルパースクリプトとフィルタスクリプトの先頭につけるクラスプレフィックスや ViewRenderer のオプションも設定します。 オプションには、 neverRendernoRendernoControllerscriptAction および responseSegment のいずれかのフラグを指定します。

  • setRender($action = null, $name = null, $noController = false) を使用すると、scriptActionresponseSegment そして noController のいずれかまたは複数を 一度に指定することができます。direct() はこのメソッドのエイリアスで、コントローラ内から簡単にコールすることができます。

    // 現在のアクションスクリプトではなく 'foo' をレンダリングします
    $this->_helper->viewRenderer('foo');
    
    // form.phtml の内容をレスポンスセグメント 'html' にレンダリングします。
    // コントローラのビュースクリプト用サブディレクトリは使用しません。
    $this->_helper->viewRenderer('form', 'html', true);
    
    [注意] 注意

    setRender() および direct() は、実際にはビュースクリプトをレンダリングしません。 実際にレンダリングを行うのは postDispatch()render() で、それらのメソッドに対するヒントを指示するだけです。

コンストラクタのオプションとして、 ビューオブジェクトを渡したり ViewRenderer のオプションを渡したりすることができます。 このオプションで指定できるのは、initView() で説明したフラグと同じものです。

$view    = new Zend_View(array('encoding' => 'UTF-8'));
$options = array('noController' => true, 'neverRender' => true);
$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view, $options);

さらに追加のメソッドがあり、 ビューオブジェクトで使用するビューの基底パスを変更することができます。 また、ビュースクリプトが自動レンダリングを行う際に使用するパスも変更することができます。 これらのメソッドでは、以下のプレースホルダのいずれかあるいは複数が使用できます。

  • :moduleDir は、現在のモジュールの基底ディレクトリを指します (規約では、これはモジュールのコントローラディレクトリの親ディレクトリとなります)。

  • :module は、現在のモジュール名を指します。

  • :controller は、現在のコントローラ名を指します。

  • :action は、現在のアクション名を指します。

  • :suffix は、ビュースクリプトのサフィックス (setViewSuffix() で設定したもの) を指します。

パス指定を制御するメソッドは次のとおりです。

  • setViewBasePathSpec($spec) は、ビューオブジェクトを追加する際に使用する基底パスを 決める際に使用するパス指定を変更します。 デフォルトの設定は :moduleDir/views です。 現在の設定を取得するには getViewBasePathSpec() を使用します。

  • setViewScriptPathSpec($spec) は、個々のビュースクリプトのパス (からビュースクリプトの基底パスを除いた部分) を決める際に使用するパス指定を変更します。 デフォルトの設定は :controller/:action.:suffix です。 現在の設定を取得するには getViewScriptPathSpec() を使用します。

  • setViewScriptPathNoControllerSpec($spec) は、noController が有効な場合に 個々のビュースクリプトのパス (からビュースクリプトの基底パスを除いた部分) を決める際に使用するパス指定を変更します。 デフォルトの設定は :action.:suffix です。 現在の設定を取得するには getViewScriptPathNoControllerSpec() を使用します。

ViewRenderer API の最後に紹介するのは、 実際にビュースクリプトのパスを決定するメソッドと ビューのレンダリングを行うメソッドです。以下をご覧ください。

  • renderScript($script, $name) は、指定したパスのスクリプトをレンダリングします。 オプションで、パスセグメントの名前を指定することもできます。 このメソッドを使用する際には、ViewRenderer はスクリプト名を自動的に決定することはありません。 そのかわりに、$script で指定された内容を直接 ビューオブジェクトの render() メソッドに渡します。

    [注意] 注意

    レスポンスオブジェクトにビューがレンダリングされると、 自動的に noRender を設定します。 これにより、同じビュースクリプトを間違って複数回レンダリングしてしまうことを防ぎます。

    [注意] 注意

    デフォルトでは、 Zend_Controller_Action::renderScript()ViewRendererrenderScript() メソッドへのプロキシとなります。

  • getViewScript($action, $vars) は、渡されたアクションや $vars で指定した変数の値に基づいてビュースクリプトのパスを作成します。 $vars 配列のキーは、パスを指定するためのキー ('moduleDir'、'module'、'controller'、'action' および 'suffix') のいずれかとなります。渡された変数の値をもとにしてパスを作成します。 なにも渡されなかった場合は、現在のリクエストの内容をもとにしてパスを作成します。

    getViewScript() は、noController フラグの内容によって viewScriptPathSpec あるいは viewScriptPathNoControllerSpec のいずれかを使用します。

    モジュール名やコントローラ名、アクション名にあらわれる 単語の区切りは、ダッシュ ('-') に置き換えられます。 したがって、たとえばコントローラ名が 'foo.bar' でアクション名が 'baz:bat' だったとすると、 デフォルトのパス指定をもとにしたビュースクリプトのパスは 'foo-bar/baz-bat.phtml' となります。

    [注意] 注意

    デフォルトでは、 Zend_Controller_Action::getViewScript()ViewRenderergetViewScript() メソッドへのプロキシとなります。

  • render($action, $name, $noController) は、まず $name あるいは $noController が指定されているかどうかを調べます。 指定されている場合は、ViewRenderer の対応するフラグ (それぞれ responseSegment と noController) を設定します。 次に、$action 引数が指定されていれば、 それを getViewScript() に渡します。 最後に、取得したビュースクリプトのパスを renderScript() に渡します。

    [注意] 注意

    render() を使用する際には、その副作用に注意しましょう。 レスポンスセグメント名や noController フラグに指定した内容は、そのオブジェクト内で残り続けます。 さらに、レンダリングが完了した際に noRender も設定されます。

    [注意] 注意

    デフォルトでは、 Zend_Controller_Action::render()ViewRendererrender() メソッドへのプロキシとなります。

  • renderBySpec($action, $vars, $name) は、パス指定用の変数を渡してビュースクリプトのパスを決定します。 $action および $vars の内容を getScriptPath() に、そしてその結果得られたスクリプトのパスと $namerenderScript() に渡します。

7.8.4.3.3. 基本的な使用例

例 7.5. 基本的な使用法

最も基本的な使用法は、起動ファイル内で ViewRenderer ヘルパーをヘルパーブローカに渡し、アクションメソッドで変数の値を設定するというものです。

<?php
// 起動ファイル内で
Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_ViewRenderer());
?>

<?php
// Foo モジュールのコントローラクラス
class Foo_BarController extends Zend_Controller_Action
{
    // デフォルトで bar/index.phtml をレンダリングするので、特に何もする必要はありません
    public function indexAction()
    {
    }

    // 変数 'foo' の値を 'bar' に設定して bar/populate.phtml をレンダリングします
    // ビューオブジェクトは既に preDispatch() で定義されているので、既に使用可能です
    public function populateAction()
    {
        $this->view->foo = 'bar';
    }

    // 何もレンダリングせずに別のアクションに転送します
    // 転送先のアクションで何らかのレンダリングを行います
    public function bazAction()
    {
        $this->_forward('index');
    }

    // 何もレンダリングせず別の場所にリダイレクトします
    public function batAction()
    {
        $this->_redirect('/index');
    }
}
?>

例 7.6. 自動レンダリングの無効化

アクションやコントローラによっては、自動レンダリングを無効にしたいこともあるでしょう。 たとえば、HTML 以外 (XML や JSON など) を出力したい場合や 単に何も出力したくない場合などです。 そんな場合には以下のいずれかの方法を使用します。 つまり、すべての自動レンダリングを無効にする (setNeverRender()) か、あるいは現在のアクションでだけ 自動レンダリングを無効にする (setNoRender()) かです。

[注意] 注意

たいていの場合は、自動レンダリングを全体で無効にする (setNeverRender()) のは無意味です。 なぜなら、ViewRenderer の唯一の存在意義が、 ビューオブジェクトを自動的に設定することだからです。

<?php
// Bar モジュールの Baz コントローラクラス
class Bar_BazController extends Zend_Controller_Action
{
    public function fooAction()
    {
        // このアクションでは自動レンダリングを行いません
        $this->_helper->viewRenderer->setNoRender();
    }
}

// Bar モジュールの Bat コントローラクラス
class Bar_BatController extends Zend_Controller_Action
{
    public function preDispatch()
    {
        // このコントローラのアクションでは決して自動レンダリングを行いません
        $this->_helper->viewRenderer->setNoRender();
    }
}
?>

例 7.7. 別のビュースクリプトの選択

アクション名から自動的に決まるスクリプトではなく、 それ以外のものをレンダリングしたくなる場合もあるでしょう。 たとえば、add アクションと edit アクションのふたつを持つコントローラがあったとしましょう。 どちらのアクションも同じ 'form' ビューを表示しますが、 そこに設定する値が異なります。 そんな場合に、それぞれでスクリプト名を変えるのは簡単です。 setScriptAction()setRender() を使用するか、あるいはヘルパーをメソッドとしてコールします。 これは setRender() を起動します。

<?php
// Foo モジュールの Bar コントローラクラス
class Foo_BarController extends Zend_Controller_Action
{
    public function addAction()
    {
        // 'bar/add.phtml' ではなく 'bar/form.phtml' をレンダリングします
        $this->_helper->viewRenderer('form');
    }

    public function editAction()
    {
        // 'bar/edit.phtml' ではなく 'bar/form.phtml' をレンダリングします
        $this->_helper->viewRenderer->setScriptAction('form');
    }

    public function processAction()
    {
        // 何かのチェックをした後で...
        if (!$valid) {
            // 'bar/process.phtml' ではなく 'bar/form.phtml' をレンダリングします
            $this->_helper->viewRenderer->setRender('form');
            return;
        }

        // その他の処理を続けます...
    }

}
?>

例 7.8. 登録されているビューの変更

ビューオブジェクトの設定を変更したくなったとしましょう。 たとえば、ヘルパーのパスやエンコーディングを変更したくなったらどうしますか? そんな場合は、コントローラに設定されているビューオブジェクトを変更するか、 あるいは ViewRenderer の外部からビューオブジェクトを取得します。 どちらも同じオブジェクトへの参照を取得することになります。

<?php
// Foo モジュールの Bar コントローラクラス
class Foo_BarController extends Zend_Controller_Action
{
    public function preDispatch()
    {
        // ビューのエンコーディングを変更します
        $this->view->setEncoding('UTF-8');
    }

    public function bazAction()
    {
        // ビューオブジェクトを取得し、エスケープ用のコールバックを 'htmlspecialchars' に設定します
        $view = $this->_helper->viewRenderer->view;
        $view->setEscape('htmlspecialchars');
    }
}
?>
7.8.4.3.4. 高度な使用例

例 7.9. パスの指定方法の変更

場合によっては、デフォルトのパス指定があなたのサイトに うまく当てはまらないこともあるでしょう。 たとえば、すべてのテンプレートを単一のディレクトリ配下にまとめ、 デザイナにはそのディレクトリに対するアクセス権だけを与えたいといった場合です (Smarty を使用する場合などにありがちです)。 そんな場合は、ビューの基底パスをハードコーディングし、 それをアクションのビュースクリプトのパスとして使用することになります。

この例では、ビューの基底パスを '/opt/vendor/templates' とし、ビュースクリプトのパスは ':moduleDir/:controller/:action.:suffix' となるようにします。noController フラグが設定されている場合は、サブディレクトリ (':action.:suffix') からではなくトップディレクトリからのパスとして探すことになります。 最後に、ビュースクリプトのファイルの拡張子として 'tpl' を設定します。

<?php
/**
 * 起動ファイル
 */

// 別のビュー実装を使用します
$view = new ZF_Smarty();

$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
$viewRenderer->setViewBasePathSpec('/opt/vendor/templates')
             ->setViewScriptPathSpec(':module/:controller/:action.:suffix')
             ->setViewScriptPathNoControllerSpec(':action.:suffix')
             ->setViewSuffix('tpl');
Zend_View_Controller_HelperBroker::addHelper($viewRenderer);

例 7.10. 単一のアクションから複数のビュースクリプトをレンダリングする例

時には、複数のビュースクリプトをひとつのアクションで処理したいこともあるでしょう。 これは、非常に直感的な方法で実現できます。単に render() を必要なだけコールすればいいのです。

<?php
class SearchController extends Zend_Controller_Action
{
    public function resultsAction()
    {
        // $this->model に現在のモデルが設定されているものとします
        $this->view->results = $this->model->find($this->_getParam('query', '');

        // render() は、デフォルトでは ViewRenderer へのプロキシとなります。
        // まず form を、そして results をレンダリングします
        $this->render('form');
        $this->render('results');
    }

    public function formAction()
    {
        // 何もしなくても、ViewRenderer が自動的にビュースクリプトをレンダリングします
    }
}

7.8.5. 独自のヘルパーの作成

アクションヘルパーは、抽象クラス Zend_Controller_Action_Helper_Abstract を継承して作成します。 ここには、基本的なインターフェイスやヘルパーブローカが使用する必須機能などが含まれています。 具体的には、次のようなメソッドです。

  • setActionController() を使用して、現在のアクションコントローラを設定します。

  • init() はヘルパーブローカによって起動時に実行され、 ヘルパーを初期化します。これは、 アクションチェイン内の複数のコントローラで同一のヘルパーを使用している場合に 状態をリセットする際などに便利です。

  • preDispatch() はディスパッチアクションの前に実行されます。

  • postDispatch() はディスパッチアクションが終了した後で実行されます。 preDispatch() プラグインがアクションの処理をスキップした場合も、 これは実行されます。後始末などをここで行います。

  • getRequest() は現在のリクエストオブジェクトを取得します。

  • getResponse() は現在のレスポンスオブジェクトを取得します。

  • getName() はヘルパーの名前を取得します。 クラス名にアンダースコアが含まれる場合は最後のアンダースコア以降の文字、 そうでない場合はクラス名全体を返します。たとえば、クラス名が Zend_Controller_Action_Helper_Redirector の場合は Redirector を、クラス名が FooMessage の場合はそのままの名前を返します。

オプションで、ヘルパークラスに direct() メソッドを実装することもできます。これを定義しておくと、 ヘルパーブローカのメソッドであるかのようにそのヘルパーを扱えるようになります。 これにより、一度だけ使用するようなヘルパーが扱いやすくなります。 たとえば、redirectordirect()goto() のエイリアスとなっているので、このようにして使用することができます。

<?php
// /blog/view/item/id/42 にリダイレクトします
$this->_helper->redirector('item', 'view', 'blog', array('id' => 42));
?>

内部的には、まずヘルパーブローカの __call() メソッドが redirector という名前のヘルパーを探し、 それからそのヘルパーで direct メソッドが定義されているかどうかを調べ、 渡された引数でそのメソッドをコールしています。

独自のヘルパークラスを作成した場合は、 上で説明したようにしてそれを利用できるようにしておきましょう。