Zend_Formのデコレータ
今までの例で見たとおり、Zend_Formを利用してフォームを出力すると自動的にformタグやdlタグなどが付加されていました。では、これはどのような仕組みで実現されているのでしょうか? また、ここで出力されているタグをカスタマイズすることは可能なのでしょうか?
Zend_Formでは、描画がどのように行われるかを制御する仕組みは「デコレータ」と呼ばれています。デコレータというとフォームやフォーム要素を装飾する仕組みのように聞こえますが、デコレータはそれだけでなく、そもそもどのような内容が出力されるかを含めて決める仕組みです。
デコレータは複数登録することが可能です。これらのデコレータは順番に呼び出されて、フィルタのように前のデコレータが加工した結果を受け取って、それを加工し、次に登録されているデコレータに渡します。
フォームのデコレータ
まず、フォーム全体がどのように描画されているかを見て行きましょう。フォームの描画はそのフォームに登録されているデコレータが順番に呼ばれることで行われます。Zend_Formが標準で利用しているデコレータはZend FrameworkのZend/Form.phpの_loadDecoratorメソッドに記述されています(リスト4)。
addDecoratorメソッドはフォームにデコレータを追加するためのメソッドで、addDecorator($decorator, $options)の2つの引数で呼び出します。ここで$decoratorはデコレータのインスタンスないしデコレータの名前、$optionsはそのデコレータへのオプションを配列にしたものを渡します。リスト4を見てみると、標準ではFormElementsデコレータ、HtmlTagデコレータ、Formデコレータが順番に作成・登録されていることが分かります。
$this->addDecorator('FormElements')
->addDecorator('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form'))
->addDecorator('Form');
));
これはどのように描画に反映されるのでしょうか? 前の例で取り上げたフォームについて、どのデコレータが出力のどの部分を担当しているかを示したのが図4です。頭と最後のformタグはFormデコレータ、その間にあるdlタグはHtmlTagデコレータ、そして中身はFormElementsデコレータによって出力されています。
フォーム要素のデコレータ
同じように、フォーム要素もデコレータによって描画されています。標準ではリスト5にあるデコレータを利用しています。
$this->addDecorator('ViewHelper')
->addDecorator('Errors')
->addDecorator('HtmlTag', array('tag' => 'dd'))
->addDecorator('Label', array('tag' => 'dt'));
このように、標準では上の4つのデコレータを利用して描画を行っています。
デコレータ関係のメソッド
フォーム(Zend_Form)にもフォーム要素(Zend_Form_Element)にもデコレータを追加・削除・設定するためのメソッドは同じようなものが準備されています。まず最初に、これらのクラスで共通なデコレータの追加・削除・設定のためのメソッドの一覧を示します。
| メソッド名 | 引数名 | 説明 |
| addDecorator | $decorator, $options | デコレータ$decoratorを追加します。$optionsはデコレータへのオプション(省略可能、どのようなデコレータがどのようなオプションを利用するかについては後にある標準で添付されているデコレータを参照して下さい)。 |
| addDecorators | $decorators | 複数のデコレータを登録します。$decoratorsは配列。 |
| setDecorators | $decorators | 現在登録されているデコレータを削除し、複数のデコレータを登録します。$decoratorsは配列。 |
| getDecorator | $name | 登録されている名前が$nameのデコレータを返します。 |
| getDecorators | なし | 登録されている全てのデコレータを返します。 |
| removeDecorator | $name | 登録されている名前が$nameのデコレータを削除します。 |
| clearDecorators | なし | 登録されている全てのデコレータを削除します。 |
また、この他にZend_Formクラスにはそのフォームに含まれるフォーム要素のデコレータを全て変更するメソッドsetElementDecoratorsメソッドがあります。
では、これらを利用してデコレータを変更してみましょう。標準ではフォームはdl、dt、dlタグを利用して描画されますが、これをul、liタグを利用して描画するように変更します(リスト6)。
public function decoratorAction()
{
$form = new Zend_Form;
$form->clearDecorators();
$form->addDecorator('FormElements')
->addDecorator('HtmlTag', array('tag' => 'ul',
'class' => 'zend_form'))
->addDecorator('Form');
$this->addElements($form);
$form->setElementDecorators(array('ViewHelper',
'Label',
array('HtmlTag', array('tag' => 'li'))));
$this->view->assign('form', $form);
return $this->render('index');
リスト6では、まずフォームで利用しているデコレータを削除した上で、addDecoratorメソッドで追加したデコレータではulを利用するように変更してます。更にsetElementDecoratorsで各フォーム要素について、liタグを描画するようにしています。これを描画したものは図5となります。


