いろいろ準備中

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

4月 9th, 2008 Posted in Zend Framework

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'
)

のような設定になっていて、initJsonContext()で、自動でJSONにシリアライズする機能が有効な場合には、ビューレンダラーアクションヘルパーを無効にし、postJsonContext()でJSONへのシリアライズおよびレスポンスオブジェクトに値を設定しています。

コールバック関数は、$callbackにコールバック関数名が指定されていると仮定すると以下のような手順で走査されます

  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'),
	        )
	    ));
	}
}
  1. One Response to “[Zend Framework] Zend_Controller_Action_Helper_ContextSwitchで独自のコンテクストを追加する方法”

  2. By Cekar on 11月 13, 2008

    I don’t understand youe explication… :(

    Regards

コメントを投稿する