日記
次世代のフォーム処理 その3Edit

ZFormが使っていたアプローチをHTML_QuickFormに適用できないか、試しに検討。HTML_QuickForm関連クラス自体を書き直すのではなく、外付けで拡張する方法で。

外付けで拡張するとなると、HTML_QuickForm_Elementたちをいちいち拡張するわけにはいかない*1から、できるのはせいぜいHTML_QuickForm本体を拡張したクラスを作って、従来の各関係クラスの機能やインターフェースとの互換性を確保したまま、Ajax対応の仕組みを追加するアプローチだろう。

HTML_QuickForm_Rendererを拡張しちゃえば、出力部分はかなり大幅にいじれるけど、Rendererは基底クラスは単なるインターフェース定義で、実装は各派生クラスでやっちゃってるから、一カ所直せば済むって話にはならなそうだ。手を出さない方が無難だろう*2

となると、HTML_QuickFormにAjax関連の設定を追加するためのメソッドを追加し、HTML_QuickForm::acceptあたりを互換性を持ったまま書き換えて、追加されたAjax関連の設定を見ながら、必要なJavaScriptコードを吐き出す感じかなー。その際には各elementがIDを持っていない場合は、IDを振る仕組みとかも必要そうだ。イベントハンドラー自体は直接element出力時に出力しなくても、IDさえ分かるなら後付けでEvent.observeできる。

というわけで、まとめてみる。

  • HTML_QuickFormを拡張したHTML_QuickForm_Exを作る。$form =& new HTML_QuickForm()の部分を$form =& new HTML_QuickForm_Ex()に変えるだけで、従来のHTML_QuickFormを使っていたコードは完全に動作するようにする。
  • HTML_QuickForm_Ex::addAjaxHandler(mixed $element, string $event, mixed $callback, array $ajaxOptions)を追加し、各element($element == __ALL__の場合はform自体)にAjax拡張用の情報を追加する。
    • コールバックの実行をXmlHttpRequestがonCompleteな場合のみ対応するのならば、このようなメソッドでいいけど、コールバックのパターンを増やしたいならば、インターフェースをもっと練る必要がある
    • HTML_QuickForm_Ex::removeAjaxHandler(mixed $element, string $event, mixed callback)も用意しておいた方がいいだろう
  • HTML_QuickForm_Ex::accept(&$renderer)で、HTML_QuickForm::accept相当の機能を実行した後に、必要なJavaScriptコードを出力する機能を追加する
    • Renderer_Defaultの場合は、$renderer->_hiddenHtmlにJavaScriptコードを追加すればいいだろう(JavaScriptの実行順序を考えると、$renderer->_htmlにコードを追加する必要があるかも。いや、$render->_hiddenHtmlにすべて出力した上で、onloadで初期化コードを呼ぶようにすれば問題ないかな?)。
    • toArrayなRendererの場合は、$renderer->_ary['javascript']にJavaScriptコードを追加すればいいかな。初期化周りの問題は上と同じ。
    • toObjectは使ったことないんで(Flexyは使ってない)よくわからないけど、多分toArrayな場合と同様に、$renderer->_obj->javascriptにJavaScriptコードを追加すればいいんだよね?
    • その他のRendererは使わないんでパス。JavaScriptコードさえ生成できていれば、出力を追加するのは簡単だろう。
  • その他懸案事項
    • Rendererに割り込むあたりは、外部オブジェクトのプライベート変数を外からばりばり書き換えるアプローチなんで、将来の互換性は厳しい。
    • javascript側のコードを書いて、考えていたような処理がJavaScriptでできるかどうか試してみないとな。まだ単純なprototype.jsのテストコードしか書いたことがない。
    • HTML_QuickFormが出力するJavaScriptバリデーションコードと、主に実行順序的にバッティングしないかどうか検証が必要。確かあれはformのonsubmitに直接イベントハンドラーを書いていたはずだけど、prototype.jsでEvent.observeした場合は、どういう実行順序になるんだろう? あるいは上書き?
    • そういやコールバックをどうやって記述するか全然考えてない。多分普段はSmartyと組み合わせて使うだろうから、Smartyテンプレート側に記述するのが無難? あるいはコールバック関数の内容自体もここで登録できるようにする方がいい?
    • elementにIDがない場合にIDを振る処理は、acceptの最初にやるべきか。自動生成したUNIQUE PREFIX+element名とかにIDを固定しちゃった方が扱いは楽なんだけどな。
    • どうせprototype.jsを使うんだったら、Ajax.Updaterとかも使いたくなりそうだけど、仕組みが複雑になりすぎるかな?

*1 HTML_QuickForm経由の自動生成ではなく、HTML_QuickForm_Elementを直接newする使い方も珍しくないから、Elementレベルで拡張してしまうと互換性的に厳しい

*2 と書いてからRenderer周辺を読み直してみたら、やっぱりRendererの各実装は(直接Rendererを書き換えないまでも)意識しないわけにいかないっぽい。toHtml、toArray、toObjectの3パターンを意識しておけばいいのかな?

Published At2006-03-09 00:00Updated At2006-03-09 00:00