Zend_Formを使う時の注意
Zend_Formはとても便利です。
フォームに関するルーチンワーク(入力フォーム作成、バリデータ定義、確認フォーム作成)を定義ファイル1つに置き換えることができます。
ところが、定義ファイルを少し更新すると、動作がおかしくなることがちょくちょくあります。
1つ目はsetElementDecoratorsとsetElementFiltersの使い方。
このメソッドを呼び出すと、個別のエレメントで指定していたデコレータとフィルターが消されます。
よって、下記のような書き方は間違っています。
[test]
form.elementFilters.trim = “StringTrim”
form.elements.name.options.filters.lower.filter = “StringToLower”
この場合、StringTrimだけがフィルタとして登録されるので、エレメントごとにデコレータやフィルタが違う場合、すべて個別に指定しましょう。
2つ目は、カスタムフィルタなどフィルタを定義し、そのフィルタコンストラクタにオプションを定義したい時の制限です。
[test]
form.elements.name.options.filters.myfilter.filter = “MyFilter”
form.elements.name.options.filters.myfilter.filter.options.param2 = “second option”
form.elements.name.options.filters.myfilter.filter.options.param1 = “first option”
カスタムフィルタの定義は上のような形で良いのですが、MyFilterに渡すコンストラクタオプションが、optionsで指定した順番に依存し、
名称は無視されます。したがって、上記の定義例ではMyFilter::__construct($param2, $param1)が呼ばれることになります。
Zend_Form_Elementクラス内の_loadFilterメソッドで、実際にフィルタをロードしているのですが、
インスタンス作成は下記のコードを使用しています。
if (empty($filter['options'])) {
$instance = new $name;
} else {
$r = new ReflectionClass($name);
if ($r->hasMethod('__construct')) {
$instance = $r->newInstanceArgs((array) $filter['options']);
} else {
$instance = $r->newInstance();
}
}
このRefrectionClassのnewInstanceArgsメソッドは、引数の配列の順番が、コンストラクタの引数の順番に該当するようになっています。
せっかくRefrectionしているのだから、順番ではなくて引数名をハッシュで指定できれば良いのですが・・・残念。
したがって、filterのオプション定義の場合は、コンストラクタの引数の順番と同じ順序で定義しましょう。
以下の書き方の方が、理解しやすいです。
[test]
form.elements.name.options.filters.myfilter.filter = “MyFilter”
form.elements.name.options.filters.myfilter.filter.options.1 = “first option”
form.elements.name.options.filters.myfilter.filter.options.2 = “second option”