fuelphpのfieldsetがもったいないので拡張してみた

fuelphpのfieldsetはすごく便利です。 formの出力とバリデーションが一体となって、似たようなコードを何回も欠かずに済みますし、文言の修正等も一箇所ですむようになります。 でも、webで検索していろいろ見ると、皆さんview画面が自由にカスタマイズできないから使えないと言ってバッサリ切ってしまっています。 すごくもったいないです。 かという自分も、view画面はきっちりと自分で作りたい派(というより仕事内容的に作らざるを得ない派)なので、fieldsetは使えないでいました。 しかし、個人サイトを作るときにfieldsetを使って以来、使えないのがストレスになってきたので、拡張して使えるようにしてみました! これでストレス無く、制作が簡単なfieldsetを使うことができます

どう拡張したのか

coreをいじるのは嫌だったので、継承したクラスたちをpackageでまとめるという形にしました。 できるようにしたのは

  • viewで簡単にinputタグ系とlabel系、エラー系を分けて出力できるようにした(メイン)
  • モデル側でfieldsetをまとめて書きたいけど、それぞれの画面で入力項目が微妙に違うよ!って場合用にaddだけじゃなくてremoveメソッドを追加
  • ついでにfieldsetにadd_textやadd_checkboxなどhtmlタグに沿ったaddメソッドを追加
  • さらについでに自分のよく使う日付選択に沿ったaddメソッドを追加

です。 htmlタグに沿ったaddメソッドを追加できるようにする部分はkenjiさんの FuelPHP の Fieldset を使おう(Form の自動生成) を参考にさせていただきました。

使い方

viewformという名前でgithubで公開しています。 使う前の準備としては次の4点です。

  1. githubよりダウンロード or チェックアウトして、fuel/packages/viewformに展開
  2. fuel/app/config/config.phpの中の
1
'packages' => array(...)

のarrayの中に’viewform’を追加

  1. (忘れがち)fuel/app/config/config.phpの中の
1
'whitelisted_classes' => array(...)

のarrayの中に’ViewForm¥¥fieldset’を追加
(viewにviewform¥fieldsetを渡すために必要です)

  1. (忘れがち)fuel/core/config/form.phpをfuel/app/config/form.phpにコピーし、中の
1
'inline_errors' => false,

をtrueに<
(これをやらないとエラー各項目でのエラーが表示されません)

実際に使うときはcontroller側は普通のfieldsetと大して変わりません。 適宜html用ショートカットメソッドを使ってラクラクーと書いてください。 view側はcontroller側から渡されたfieldsetインスタンスを使って

1
echo $fieldset->field('nickname')->label_text(); echo $fieldset->field('nickname')->field_text(); if $fieldset->field('nickname')->has_error()){ echo $fieldset->field('nickname')->error_text(); }

といった形でlabelとinputタグが別々にかけます。 もちろんタグの属性を引数に渡すこともできます。

1
echo $fieldset->field('nickname')->label_text(array('class'=>'control-label'));

(ただし、add_dateだけはちょっと特殊)

具体例

最後に、ひとつ自分が作ったものをそのままコピペしてみます 実際に使ってるコードなので、smartyだったりメソッド全部網羅してなかったりtwitter bootstrapだったりするのは勘弁してください controller側

1
public function action_user() { $fieldset = $this->_fieldset(); $fieldset->repopulate(); $val = $fieldset->validation(); if ($val->run()) { //保存処理 $user = Model_User::forge(); $saveKeys = array( 'nickname', 'gender', 'country', 'email', 'birthday',); foreach ($saveKeys as $key) { $user->$key = $val->validated($key); } $user->save(); return Fuel¥Core¥Response::redirect("setting/finished"); } $smarty = Parser¥View_Smarty::forge('setting/user.tpl') ->set('fieldset', $fieldset); return Fuel¥Core¥Response::forge($smarty); } /** * * @return ViewForm¥Fieldset */ protected function _fieldset() { $fieldset = ViewForm¥Fieldset::forge(); // textboxはadd をadd_textにするだけで使える $fieldset->add_text('nickname', 'ニックネーム') ->add_rule('required') ->add_rule('max_length', 10); // radio 用は add_radio // value => 表示名 の配列 で選択肢を設定 $genders = array('male' => "男性", 'female' => "女性",); $fieldset->add_radio('gender', '性別', $genders) ->add_rule('required'); // radio 用は add_select // value => 表示名 の配列 で選択肢を設定 (radioと同じ) $countries = array('jp' => '日本','us' => 'アメリカ'); $fieldset->add_select('country', '国籍', $countries) ->add_rule('required'); $fieldset->add_text('email', 'メールアドレス') ->add_rule('required') ->add_rule('valid_email'); // 年月日用selectbox // 年を数値で指定 または 現在の年からの差で指定できる // // ちなみにvalidate後はunixtimeに変換されている $fieldset->add_date_select('birthday', '誕生日', 1900, +0); return $fieldset; }

view側

1
{@Form::open(['class' => 'form-horizontal'])@} {@$fieldset->show_errors()@} <fieldset> <div class="control-group {@if $fieldset->field('nickname')->has_error()@}error{@/if@}"> {@$fieldset->field('nickname')->label_text(['class'=>"control-label"])@} <div class="controls"> {@$fieldset->field('nickname')->field_text(['class'=>'span9'])@} <span class="help-inline">{@$fieldset->field('nickname')->error_text()@}</span> </div> </div> <div class="control-group {@if $fieldset->field('gender')->has_error()@}error{@/if@}"> {@$fieldset->field('gender')->label_text(['class'=>"control-label"])@} <div class="controls"> {@$fieldset->field('gender')->field_text()@} <span class="help-inline">{@$fieldset->field('gender')->error_text()@}</span> </div> </div> <div class="control-group {@if $fieldset->field('country')->has_error()@}error{@/if@}"> {@$fieldset->field('country')->label_text(['class'=>"control-label"])@} <div class="controls"> {@$fieldset->field('country')->field_text()@} <span class="help-inline">{@$fieldset->field('country')->error_text()@}</span> </div> </div> <div class="control-group {@if $fieldset->field('email')->has_error()@}error{@/if@}"> {@$fieldset->field('email')->label_text(['class'=>"control-label"])@} <div class="controls"> {@$fieldset->field('email')->field_text()@} <span class="help-inline">{@$fieldset->field('email')->error_text()@}</span> </div> </div> <div class="control-group {@if $fieldset->field('birthday')->has_error()@}error{@/if@}"> {@$fieldset->field('birthday')->label_text(['class'=>"control-label"])@} <div class="controls"> {@$fieldset->field('birthday_year')->field_text(['class' => 'span2' ])@}年 {@$fieldset->field('birthday_month')->field_text(['class' => 'span2' ])@}月 {@$fieldset->field('birthday_day')->field_text(['class' => 'span2' ])@}日 <span class="help-inline">{@$fieldset->field('birthday')->error_text()@}</span> </div> </div> <div class="control-group"> <div class="controls"> <div class="actions"> {@Form::submit('submit', '保存',['class' => 'btn btn-primary btn-large'])@} </div></div> </div> </fieldset> {@Form::close()@}