Webtech Walker

sfFormのformtterで出力結果のHTMLを変更する

最近sfFormerと名乗ってもいいくらいsfFromしかやってないです。今回はformatterについてのメモ。

formatterを自分で定義すればrender()で出力するHTMLを変更できます。実装もそんなに難しくないので、ulをdtに変えるだけとかだったら割とさっくりできます。ただドキュメントがないからソース読んで察するしかないのが難点。

今回は以下のようなフォームをdlで実装してみます。ラジオボタンの中にテキストボックスが入ってるのがなかなかやっかい。

フォームのキャプチャ

出力したいHTMLのソースはこんな感じ。

<dl>
    <dt><input type="radio" name="name_type" id="name_type_1" value="1" /><label for="name_type_1">個人</label></dt>
    <dd><input type="text" name="personal_name" /></dd>
    <dt><input type="radio" name="name_type" id="name_type_2" value="2" /><label for="name_type_2">法人</label></dt>
    <dd><input type="text" name="company_name" /></dd>
</dl>

実装はこんな感じ。

class inputForm extends sfForm
{
    public function configure() {
        // ラジオボタンのwidget作成
        // formatterにcallbackを渡す
        $this->widgetSchema['name_type'] = new sfWidgetFormSelectRadio(
            array(
                'choices' => array('1' => '個人', '2' => '法人'),
                'formatter' => array($this, 'nameTypeFormatter'),
            )
        );

        // 名前の入力フィールドwidget作成
        $this->widgetSchema['personal_name'] = new sfWidgetFormInput();
        $this->widgetSchema['company_name']  = new sfWidgetFormInput();

        // 作成したwidgetの名前の配列をoptionにセット
        $this->widgetSchema['name_type']->addOption('inputNames', array('personal_name', 'company_name'));
    }

    public function nameTypeFormatter($widget, $inputs) {
        $row = array();
        $inputNames = $widget->getOption('inputNames');

        // 列を作成
        foreach ($inputs as $key => $input) {
            $dt = $widget->renderContentTag('dt', $input['input'].$input['label']);
            $dd = $widget->renderContentTag('dd', $this[$inputNames[$key]]->render());

            $row[] = $dt.$dd;
        }

        // 列を連結してdlでラップ
        $dl = $widget->renderContentTag('dl', join("\n", $row));

        return $dl;
    }
}

formatterの中で入力フィールドもrender()で出力してます。これでviewのほうでは、

<table>
    <tr>
        <th>お名前</th>
        <td><?php echo $form['name_type']->render() ?></td>
    </tr>
</table>

これだけでおk。こんな感じで大体のことは実現可能です。ドキュメントできてないので詳しくはソース読まないとわかりませんが。

このエントリーをはてなブックマークに追加