Zend_FormのデコレータとZend_Config_Xmlに関する困ったメモ
Zend_Formに定義ファイルでデコレータを流し込む際のハマりどころについてメモしておきます。
XMLでの指定についてなのですが、まず、XMLのルートノードについては基本的になんでもよいのですが、第1階層はセクションとして扱われます。
セクション直下の動作では、セクションを配列のキーにしてエントリーが子要素になってわかりやすいのですが、第2階層以下では列挙型にするときの動作に差が出ます。
以下の記述では、セクション直下以降での設定を前提にしています。
基本の1
<decorators> <decorator value="HtmlTag"> <options> <tag value="div" /> </options> </decorator> </decorators>
これは、Zend_Form等にdecoratorsを設定で流し込むときに使える書き方です。
HtmlTagというデコレータにオプションでtag=>divを設定したものがロードされます。
simplexml_load_file等の仕様でデータ構造とXML記法的なギャップについて
http://d.hatena.ne.jp/noopable/20090325/1237933832
こちらで書いた、simplexml_load_file関係の挙動に関連しているのですが、デコレータを増やすとどうなるか
<decorators> <decorator first="HtmlTag"> <options> <tag value="p" /> </options> </decorator> <decorator second="HtmlTag"> <options> <tag value="div" /> </options> </decorator> </decorators>
これで、動作してくれるとよいのですが、simplexml_load_file、およびZend_Config_Xmlの仕様(?)でdecoratorというエントリーが二つあると、decorator配下にキーなしで配列が組み込まれます。
結果としてこの書き方では動作しません。
代わりに、
<decorators> <decorator first="HtmlTag"> <options> <tag value="p" /> </options> </decorator> </decorators> <decorators> <decorator second="HtmlTag"> <options> <tag value="div" /> </options> </decorator> </decorators>
配列の記法的に本来的にはdecorators以下に配列としてスタックしてほしいわけですが、Zend_Config_Xmlでそれを実現するには、親側のdecoratorsを並べる必要があります。
これで、動いてくれるとよいのですが、この書き方ではやはり動作しません。ここからはZend_Form関係のaddDecorators内の仕様の影響です。動くように書くには
<decorators> <decorator first="HtmlTag"> </decorator> <options> <tag value="p" /> </options> </decorators> <decorators> <decorator second="HtmlTag"> </decorator> <options> <tag value="div" /> </options> </decorators>
オプションを入れ子にせず、外に出します。単数のときは、入れ子にする必要があり、複数使うときは入れ子から出さなければいけません。
ですので、入れ子から出した場合は単独では使えません
<decorators> <decorator first="HtmlTag"> </decorator> <options> <tag value="p" /> </options> </decorators>
調整できるか
Zend_Config_Xmlで、その辺の動作をさせている部分は、Zend_Config::_toArray内の配列の構築部分です。
<?php if (array_key_exists($key, $config)) { if (!is_array($config[$key]) || !array_key_exists(0, $config[$key])) { $config[$key] = array($config[$key]); } $config[$key][] = $value; } else { $config[$key] = $value; }
こんな感じで、既にキーがあるとき(同じ親の下で同じキーが重複した場合)配列を数値添字で結合していきます。
Zend_Config_Xmlではzfというnamespaceが使えるので、namespaceを使って、特定の要素をcollection用に数値添字にするように書き換えれば問題は減りそうですが、当面、書き方を覚えて対応しておくことにしました。