FuelPHP の Fieldset クラスをこんな風に拡張してまーす、という話

2012/12/07

FuelPHP Advent Calendar 2012 の 7 日目の記事です。昨日は @ounziw さんの『ユニットテストのすすめ』でした。

↑関係ないけど、昨日イカセンター新宿総本店で食べた紋甲イカ。美しい。

みなさんこんにちは。7 日目担当の omoon です。

2012 年は、5 月の PHP カンファレンス関西で、

この話をしたのをきっかけに、まさに、FuelPHP とともに forge し続けた 1 年でした。2012 年も残り少ないですが、悔いの残らないように forge しまくって、2013 年も引き続き forge しまくりたいと思います。

さて、FuelPHP では、フォームを扱う場合、Form クラスと、Validation クラスという 2 つのクラスを使います。

また、それらをまとめてオブジェクト指向風に扱うための Fieldset クラスというクラスも用意されています。

僕の場合は、基本的に Fieldset クラスを使ってフォームを扱うのですが、使っているうちに、ここがこうなってたら便利なのになー、とか、こういうメソッドあればいいのに、っていうのがいくつか出てきたので、自分用に Fieldset クラスを拡張しています。

今日はその一部を晒します。

この拡張でなにがやりたいか

この拡張でやりたいことを簡単にまとめると、

  1. view でのレイアウトの自由度を高めたい
  2. 自動的に CSRF トークンを含めたい
  3. フォーム要素の生成でよくあるパターンをサッと呼び出したい

の 3 つになります。

下で詳しく説明しますが、やりたいことをざっくりコードで説明すると、

コントローラで↑このように、Myfieldset::forge()して、

ビューファイルで↑このように書いて、

結果として、↑このような出力を得たい、ということです。

表示はこうなります。

ad00a380ef1b41bf2191d934ffce8a62

Myfieldset クラスはこんな感じです。

わかりにくいですね。以下、説明します。

ポイント

各要素のラベルと html が別々に呼び出せるので、view ファイル上でのレイアウトの自由度が上がる

各要素のラベルと html が、それぞれ

$form['age']['label']
$form['age']['html']

として別々に呼び出すことができるようになります。

Form クラスのbuild()メソッドは、ラベルと html 要素を、決まったレイアウトを一気に出したい場合には便利なんですが、ちょっとレイアウトを触りたい時にうまくいきません。

なので、こうやって別々に呼び出せるようにしておくと、view ファイル側で色々といじれて嬉しいです。

CSRF トークンが自動的に含まれるので、めんどくさくないし、出し忘れたりしない

基本的に、フォームには、セキュリティ対策としての CSRF トークンを含めることになるので、何も考えなくても勝手に追加されるようにしました。

これで、view ファイルから

$form['open']

と呼べば、明示的に追加しなくても、

<form action="http://localhost:8080/post_url" method="post" id="form_sample" accept-charset="utf-8">
<input name="fuel_csrf_token" value="c9313a400c254e58c0d23f7fd599c297" type="hidden" id="form_fuel_csrf_token" />

みたいに、出力されるようになって嬉しいです。

フォーム要素の生成でよくあるパターンをサッと呼び出せるので、何回も同じこと書かなくて良い

例えば、数値型の入力を受け付ける場合は、値が数値かどうか必ずチェックします。また、ime-mode なんかも適切に設定してあげると親切です。

なので、

return $this->add(
    $name,
    $label,
    array(
        'class' => 'input-medium',
        'style' => 'ime-mode:disabled'
    )
)->add_rule('valid_string', 'numeric')->set_template('{field}');

という感じにして、入力値が数値かどうかの判定をadd_ruleしたり、ime-mode:disabledをスタイル指定したりしています。

これで、コントローラ側では、

$fieldset->addTextForNumeric('age', '年齢');

と書くだけです。スッキリ!スッキリ!

このように、自分がよく使う要素を生成するメソッドを、スタイルやバリデーション込みで用意しておけば、コントローラからさっと呼び出せて便利です。

ちなみに、ぼくのかんがえたさいきょうの拡張は、こんなやつが色々と溜まってきて良い感じになっているのですが、今回は、ラジオボタンで、選択肢を改行するパターンと改行しないパターンを例に上げてみました。

public function addRadioInline($name, $label, $options)
{
    return $this->add(
        $name,
        $label,
        array(
            'type'    => 'radio',
            'options' => $options,
        )
    )->set_template('{fields}<label class="radio inline">{field}{label}</label>{fields}');
}

public function addRadioWithBr($name, $label, $options)
{
    return $this->add(
        $name,
        $label,
        array(
            'type'    => 'radio',
            'options' => $options,
        )
    )->set_template('{fields}<label class="radio">{field}{label}</label>{fields}');
}

こんな感じで、set_templateメソッドを使って、要素生成時のタグの出し分けをするようにしています。

えーっと、結構長くなってきたので、そろそろ、このあたりで。。

フォームの作りこみは、システムのユーザビリティに大きく影響しますので、これからもどんどん拡張していって良い感じに育てていきたいと思っています。

明日は、@web2citizen さんの、『FuelPHPのスパムフィルタパッケージ』です。楽しみですね!

では、みなさん、良いクリスマスを!そして、来年もガンガン forge しましょう!

<< 古い記事