Wadslog

[Zend Framework] Zend_Controller_Action_Helper_ContextSwitchで独自のコンテクストを追加する方法

Apr 9, 2008

Zend_Controller_Action_Helper_ContextSwitch(長い)で、独自のcontextを追加する方法を書きます。 デフォルトで組み込まれている機能(xmlとjson形式)の使い方は前のエントリーを参照ください。今回は自分の都合で、gif形式での方法を書きます。 新しいコンテキストを追加する方法は、addContext()を使います。 インターフェースは以下のようになっています。``` public function addContext($context, array $spec)

$contextでコンテキスト名を指定し、$specでコンテキストの設定を配列で指定します。$contextがすでにあるコンテキストと重複した場合は、Zend\_Controller\_Action\_Exceptiongがスローされます。 $specには、配列のキーで設定名、値で設定値を指定します。設定名は、suffix、headers、callbacksがあります。ひとつづつ説明していきます。 **suffix** ViewRenderer に登録されているビュースクリプトのサフィックス(デフォルトでは .phtml)の前に追加するサフィックスです。ViewRendererを有効にしている場合、fooAction()のビュースクリプト名は、デフォルトでfoo.phtmlとなりますが、ContextSwitchアクションヘルパーでコンテキストスイッチを行うと、参照されるビュースクリプトはfoo.{suffix名}.phtmlとなります。 ‘suffix’=>‘gif’

のように設定した場合は、foo.gif.phtmlというファイルがビュースクリプトとなります。 **headers** ヘッダの名前を配列のキー、値を配列の値とした値で、コンテキストスイッチを行ったときにレスポンスヘッダに追加したいヘッダを指定します。Content-Typeは必須だとおもうので、たとえば ‘headers’=>array(‘Content-Type’=>‘image/gif’)

という設定をします。個人的にはもう少し設定しますが今回は割愛します。 **callbacks** キーに'init'や'post'を含む配列で、それぞれコンテキストの初期化や後処理の際に使用するコールバック関数を指定します。たとえば、 ‘callbacks’ => array( ‘init’ => ‘initGifContext’, ‘post’ => ‘postGifContext’ )

のように設定してある場合、initGifContext()がinitContext()コール時に、コントローラのpostDispatch()時にそれぞれ実行されます。 デフォルトで組み込まれているjsonでは、 ‘callbacks’ => array( ‘init’ => ‘initJsonContext’, ‘post’ => ‘postJsonContext’ )


1.  $callbackが文字列なら、同名のクラスメソッドを探す
2.  $callbackが文字列なら、PHP関数を探す
3.  $callbackが配列なら、call\_user\_func()に引数として渡す
4.  ここまでで関数が見つからなければZend\_Controller\_Action\_Exceptionをスローする

これまでの説明を踏まえて、設定の例を以下に示します。```
    $spec = array(
        'suffix' => 'gif',
        'headers' => array(
            'Content-Type' => 'image/gif',
        ),
        'callbacks' => array(
            'init' => 'initGifContext',
            'post' => 'postGifContext'
        )
    );
    $this->addContext('gif', $spec);

```あとは、コールバック関数のinitGifContext()とpostGifContext()の定義です。 jsonのものを参考に、それぞれ定義してみました。 **・initGifContext() - ビューレンダラーの解除**```
public function initGifContext() {
    $viewRenderer = Zend\_Controller\_Action\_HelperBroker::getStaticHelper('viewRenderer');
    $view = $viewRenderer->view;
    if ($view instanceof Zend\_View\_Interface) {
        $viewRenderer->setNoRender(true);
    }
}

```**・postGifContext() - gifファイルの出力**```
public function postGifContext() {
    $viewRenderer = Zend\_Controller\_Action\_HelperBroker::getStaticHelper('viewRenderer');
    $view = $viewRenderer->view;
    if ($view instanceof Zend\_View\_Interface) {
        $vars = $view->getVars();
       if (@readfile($vars\['file'\]) === FALSE) {
			throw new Exception('failed readfile()');
		}
    }
}

```アクションメソッドにて、ビューファイルにfileという名前で設定(assign())したgifファイルを出力する仕様になっています。 今回は新しいコンテクストの作り方として、Zend\_Controller\_Action\_Helper\_ContextSwitchを継承したクラスに書くことにします。 **MyGifContext.php**```
<?php
require\_once 'Zend/Controller/Action/Helper/ContextSwitch.php';

class MyGifContext extends Zend\_Controller\_Action\_Helper\_ContextSwitch {
    public function \_\_construct() {
        parent::\_\_construct();
        
        $spec = array(
            'suffix' => 'gif',
            'headers' => array(
                'Content-Type' => 'image/gif',
            ),
            'callbacks' => array(
                'init' => 'initGifContext',
                'post' => 'postGifContext'
            )
        );
        $this->addContext('gif', $spec);
    }
    
    public function initGifContext() {
        $viewRenderer = Zend\_Controller\_Action\_HelperBroker::getStaticHelper('viewRenderer');
        $view = $viewRenderer->view;
        if ($view instanceof Zend\_View\_Interface) {
            $viewRenderer->setNoRender(true);
        }
    }

    public function postGifContext() {
        $viewRenderer = Zend\_Controller\_Action\_HelperBroker::getStaticHelper('viewRenderer');
        $view = $viewRenderer->view;
        if ($view instanceof Zend\_View\_Interface) {
            $vars = $view->getVars();
           if (@readfile($vars\['file'\]) === FALSE) {
    			throw new Exception('failed readfile()');
    		}
        }
    }
}

```あとはコントローラの設定です。barというアクションにコンテキストスイッチを割り当てます```
<?php
class FooController estneds Zend\_Controller\_Action {
    public function init() {
        $contextSwitch = $this->\_helper->getHelper('myGifContext');
        $contextSwitch->addActionContext('bar', 'gif')
                      ->initContext();
    }

    public function barAction() {
    	// 読み込むファイル名を取得
    	$fname = ...
    	
    	// ビュースクリプトにアサイン
    	$this->view->file = $fname;
    }
}

```MyGifContextクラスをアクションヘルパーとして登録します。ドキュメントルート直下のindex.phpに以下のように一行を追加します。```
require\_once 'MyGifContext.php';
Zend\_Controller\_Action\_HelperBroker::addHelper(new MyGifContext());

```これでつかえるようになりました。以下のようなURLにアクセスします。```
http://example.com/foo/bar/format/gif

```これでgif画像が表示されます。コンテクストを切り替えるために**/format/gif**を忘れないように追加してください。 ちなみに、先に述べたように、Zend\_Controller\_Action\_Helper\_ContextSwitchはデフォルトでxmlとjson形式に対応していると書きましたが、コンストラクタにてaddContext()でxmlとjsonのコンテキストを追加していました。```
public function \_\_construct($options = null) {
	if (empty($this->\_contexts)) {
	    $this->addContexts(array(
	        'json' => array(
	            'suffix'    => 'json',
	            'headers'   => array('Content-Type' => 'application/json'),
	            'callbacks' => array(
	                    'init' => 'initJsonContext',
	                    'post' => 'postJsonContext'
	            )
	        ),
	        'xml'  => array(
	            'suffix'    => 'xml',
	            'headers'   => array('Content-Type' => 'text/xml'),
	        )
	    ));
	}
}

comments powered by Disqus