[Zend Framework] Zend_ControllerのContextSwitchアクションヘルパーでZend_View_Interfaceが使えない件
Zend Framework1.5から新しく追加されたZend_ControllerのContextSwitchアクションヘルパーを使ってJSON形式でレスポンスを返そうとしたところ、
Fatal error: Call to undefined method Lib_ViewSmarty::getVars() in ...
というエラーが出ました。確かにここを参考に作ったSmartyのラッパーにはそのような関数はありません。そもそもZend_View_Interfaceにそういう関数のインターフェースがないのです。ということで少々Smartyラッパーに手を加えないといけません。
Zend_View_AbstractにはちゃんとgetVars()というものがあるので、これを見ることにします。
public function getVars() { $vars = get_object_vars($this); foreach ($vars as $key => $value) { if ('_' == substr($key, 0, 1)) { unset($vars[$key]); } } return $vars; }
この関数では、設定された(assign()された)値をすべて返しているようです。
処理的には、Zend_Viewクラスのプロパティーをすべて取得して、’_'で始まるプロパティーを排除しています。このクラスに設定されているプロパティは、もともとクラスに備わっているプロパティとviewに出力する値として設定された(assign()された)プロパティの2種類があります。
前者は’_'で始まりますのでこれらを排除して、後者の値のみを返す処理になっています。初めて知ったのですが、assign()では、設定する値の名前が’_'で始まる場合にはExceptionをスローする仕組みになっているので、このgetVars()の設定が可能になるのです。
public function assign($spec, $value = null) { // which strategy to use? if (is_string($spec)) { // assign by name and value if ('_' == substr($spec, 0, 1)) { require_once 'Zend/View/Exception.php'; throw new Zend_View_Exception('Setting private or protected class members is not allowed', $this); } $this->$spec = $value; ... }
一方、リファレンスマニュアルからコピペしたSmartyのラッパーではそのような処理は実装されておらず、たとえば以下のようなことが可能でした。
$this->view->_foo = "foo";
とactionメソッドで設定して、viewにて
{$_foo}
表示は以下のようになります
foo
というわけで、Smartyラッパのほうも同じような処理にしたかったのですが、Smartyクラスのプロパティーが’_'で始まっていなかったのでこの方法は使えません。そのかわり、get_template_vars()という関数を引数無しで呼び出せば値が取得できるのでこれを用いることにします。
以下のように実装してみました。
public function getVars() { return $this->_smarty->get_template_vars(); }
ちゃんと出力されるかどうか試してみます。actionメソッドに以下のとおり書きます。
$this->view->foo = "foo"; $this->view->hoge = array("fuga"=>"fuga", "piyp"=>3); var_dump($this->view->getVars());
出力は以下のようになりました。
array(3) { ["SCRIPT_NAME"]=> string(10) "/index.php" ["foo"]=> string(3) "foo" ["hoge"]=> array(2) { ["fuga"]=> string(4) "fuga" ["piyp"]=> int(3) } }
うーむ。SCRIPT_NAMEという身に覚えのないものがセットされていますね。これはSmartyクラスのコンストラクタで自動的にセットされているようです。
あまりすっきりしないですが、キーが’SCRIPT_NAME’の値をunset()することにします。
public function getVars() { $vars = $this->_smarty->get_template_vars(); unset($vars["SCRIPT_NAME"]); return $vars; }
これで再度表示してみます。
array(2) { ["foo"]=> string(3) "foo" ["hoge"]=> array(2) { ["fuga"]=> string(4) "fuga" ["piyp"]=> int(3) } }
今度はちゃんと出たようです。
getVars()を追加したあとにContextSwitchアクションヘルパーを使ってJSONでレスポンスを得ることに成功しました。
昨日やると言っていたことはまた次回ですね。