# アクションヘルパー

## 導入

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

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

## ヘルパーの初期化

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

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

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

      $flashMessenger = $this->_helper->getHelper('FlashMessenger');
      $flashMessenger->addMessage('先ほどのリクエストで、あることをしました');

- ヘルパーブローカの `__get()` 機能を使用すると、 まるでブローカのプロパティであるかのようにヘルパーを操作できます。

      $flashMessenger = $this->_helper->FlashMessenger;
      $flashMessenger->addMessage('先ほどのリクエストで、あることをしました');

- たいていのアクションヘルパーは `direct()` メソッドを実装しており、 これはそのヘルパーのデフォルトメソッドをコールします。 `FlashMessenger` の例では、 `addMessage()` をコールします。

      $this->_helper->FlashMessenger('先ほどのリクエストで、あることをしました');

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

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

## ヘルパーブローカ

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

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

    Zend_Controller_Action_HelperBroker::addHelper($helper);

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

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

      // My/Action/Helpers/ にある、名前が My_Action_Helpers で始まるヘルパーを追加します
      Zend_Controller_Action_HelperBroker::addPrefix('My_Action_Helpers');

- `addPath()` は、最初の引数にディレクトリ、 そして二番目の引数にクラスのプレフィックス (デフォルトは '`Zend_Controller_Action_Helper`') を指定します。 これは、指定したディレクトリにある指定したプレフィックスのクラスを追加します。

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

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

内部的には、ヘルパーブローカは PluginLoader のインスタンス を用いてパスを保持します。静的メソッド `getPluginLoader()` で PluginLoader を取得することもできますし、また独自の PluginLoader インスタンスを `setPluginLoader()` で設定することもできます。

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

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

ヘルパーブローかからヘルパーを取得する静的メソッドには、さらに `getExistingHelper()` と `getStaticHelper()` のふたつがあります。 `getExistingHelper()` は、すでに起動されているか、 あるいは明示的にヘルパーブローカに登録されているヘルパーのみを取得します。 存在しない場合は例外をスローします。 `getStaticHelper()` は `getExistingHelper()` と同じですが、 ヘルパースタックに登録されていないヘルパーについてはそのインスタンスを作成しようとします。 自分で設定をしたいヘルパーを取得するには `getStaticHelper()` がおすすめです。

どちらのメソッドも、引数はひとつだけです。 この引数 `$name` には、ヘルパーのショートネーム (プレフィックスを除いたもの) を指定します。

    // 'redirector' ヘルパーがブローカに登録されているかどうかを調べ、取得します
    if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
        $redirector =
            Zend_Controller_Action_HelperBroker::getExistingHelper('redirector');
    }

    // あるいは、登録されているかどうかを気にせずに単純に取得します
    $redirector =
        Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
    }

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

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

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

Zend Framework には、いくつかのアクションヘルパーがデフォルトで組み込まれています。 AJAX のオートコンプリート機能用のレスポンスを作成する AutoComplete、 アクションに応じてレスポンスの形式を変更する ContextSwitch と AjaxContext、セッション単位のフラッシュメッセージを扱う FlashMessenger、JSON 形式へのエンコードとレスポンスの送信を行う Json、 アプリケーション内から内部あるいは外部へのリダイレクトを実装できるようにする Redirector、そして コントローラ内でのビューオブジェクトの設定とビューのレンダリングを自動化する ViewRenderer です。

## 独自のヘルパーの作成

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

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

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

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

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

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

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

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

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

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

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

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