CakePHPのFormHelper入門をさくっと+複数チェックボックスとかdiv消したり

今回検索機能の実装時に初めてFormHelperを使いました。しかし元々できることを別の方法でやるために勉強するのは辛いですね。ちょっとした詰まりで悲しい気持ちになるので、同様の境遇の人の参考になればと思います。なお、細かいことはCakePHP1.3準拠です。

内容
  1. FormHelperの意義
  2. FormHelperの基本
  3. Tips
  4. 複数チェックボックスの作成
  5. 余分なdivタグやhiddenフィールドを消す

FormHelperの意義

FormHelperはPHPのコードでフォームを自動で生成してくれるものです。フォームを非常にCakePHPっぽく扱うことができるのですが、下手すると記述量が逆に増えたりもします。トータルで見るとメリットの方が多いと感じましたが、Cakeと一度限りの付き合いなら使わないという選択肢もありかと。

メリット
  • ・name属性の入力が楽になる
  • nameを単語で指定すれば、勝手にdata[Model][単語]みたいに$this->dataで取り出せる名前にしてくれます
  • ・formを連想配列で記述できる
  • CakePHPではおなじみの連想配列で書くので、HTMLのformをあまり使ったことない人には扱いやすいのかもしれません。そんな人恐らくいませんが
  • ・一部のタイプでは記述がラク
  • type=select や radio のoption部分の記述は楽です
デメリット
  • ・viewにPHPコードが混ざる
  • viewはデザイナーさんがという場合はわかりにくくなるかもしれません
  • ・デフォルトで変なコードが多々付加される
  • フォームが勝手にdivで囲まれてたりして、消すためには一々引数で指定する必要があります。結果必要な記述量は多くなりがちです

FormHelperの基本

全部マニュアルに書いてありますが、さくっと書くために必要なことだけ抜粋して単純化しています。詳しくはマニュアルをご覧ください。

記述方法

<?php echo $this->Form->メソッド('名前' , array( 'オプションの種類'  => 'オプションの値' )); ?>
だいたいこんな感じです。最初の引数でフォームのname属性、次の引数の連想配列でオプションとして属性やラベルなんかを設定します。オプションの種類はHTMLタグ内のプロパティ名と対応しているものが多く、フォームに添える文字列の設定等も可能です。

良く使うメソッド

以下では、'Shop'という名前のモデルを使用する、ShopsControllerのSearchアクションにおける挙動を紹介します。
create-フォームの開始

<?php echo $this->Form->create() ?>

  • //展開後
  • <form action="/Cake/shops/search" id="ShopSearchForm" method="post" accept-charset="utf-8">
  • <div style="display:none;">
  •   <input type="hidden" name="_method" value="POST" />
  • </div>

フォームタグが出力されます。また、actionが現在のアクション、idがモデル名+アクション名+Form、methodがPost、accept_charsetがDBのcharsetにデフォルトで指定されるようになっています。また、hiddenフィールドがデフォルトで出力されます。このhiddenフィールドを含む、他メソッドにおけるdivやlabelといったデフォルトで出力されるタグ類は、後述の方法で消すことができます。

end-フォームの終了

<?php echo $this->Form->end() ?>

  • //展開後
  • </form>

閉じタグが出力されます。

input(チェックボックス)

<?php echo $this->Form->input('hoge' , array('type' => 'checkbox')); ?>

  • //展開後
  • <div class="input checkbox">

  <input type="hidden" name="data[Shop][hoge]" id="ShopHoge_" value="0" />

  <input type="checkbox" name="data[Shop][hoge]" value="1" id="ShopHoge" />

  <label for="ShopHoge">Hoge</label>

  • </div>

フォーム内の要素はほとんどinputで出力します。オプションキー'type'で種類を指定します。また、inputタグにおいてはidはモデル名+要素名、nameはdata+[モデル名]+[要素名]に設定されます。フォーム要素前後への文字列の追加は、'before'、'after'のオプションキーで可能です。なおチェックボックスでは自動的にvalueプロパティ、labelタグ、divタグ、hiddenフィールドが付加されます。

input(セレクトボックス)

<?php echo $this->Form->input('hoge' , array(

  'type' => 'select' ,

  'options' => array(1,2,3)

)); ?>

  • //展開後
  • <div class="input select">

  <label for="ShopHoge">Hoge</label>

  <select name="data[Shop][hoge]" id="ShopHoge">

  •     <option value="0">1</option>
  •     <option value="1">2</option>
  •     <option value="2">3</option>

  </select>

  • </div>

selectでは、'option'キーで選択肢を配列で設定できます。セレクトボックスでは自動的にvalueプロパティ、labelタグ、divタグが付加されます。

input(テキストボックス)

<?php echo $this->Form->input('hoge' , array('type' => 'text')); ?>

  • //展開後
  • <div class="input text">

  <label for="ShopHoge">Hoge</label>

  •   <input name="data[Shop][hoge]" type="text" id="ShopHoge" />
  • </div>

テキストボックスでは自動的にlabelタグ、divタグが付加されます。

submit-入力内容の送信

<?php echo $this->Form->submit() ?>

  • //展開後
  • <div class="submit">

  <input type="Submit" value="Submit" />

  • </div>

submitは入力情報の送信ボタンを作成します。引数を指定した場合、それがvalueプロパティの値=送信ボタンの文言になります。submitには自動でdivタグが付加されます。

入力データの取得

Controller内で

//ShopsController

$this->data;

と記述することで配列として取得できます。各フォーム要素のデータは、nameプロパティの値でアクセス可能です。

例えば、以下のように記述すれば、送信した際に取得したデータをviewで確認することができます。

//ShopsController

$this->set( 'data' , $this->data );



//view search.ctp

debug($data);

Tips

余分なdivタグやhiddenフィールドを消す

デフォルトで出力されるコードたち。かなり余計なお世話です。オプション内でFALSEを記述することで消せます。個別に消すことも、まとめて消すこともできます。

  • 個別に消す
  • ・divタグ 'div' => FALSE
  • ・hiddenフィールド 'hiddenField' => FALSE
  • ・labelタグ 'label' => FALSE
  • まとめて消す
  • ・create内 ’inputDefaults’ => array(‘label’ => false,’div’ => false)

一々指定すると記述量が増えますので、メソッドを直接書き換えて、デフォルトをFALSEにすることも可能です。下記では、coreの中のform.phpをapp内にコピー→inputメソッド内のデフォルト値を書き換えとやっています。が、inputDefaults指定で十分かな?

  • //cake/libs/view/helpers/form.php
  • //app/views/helpers/form.phpにコピーして書き換え

  • 799   $divOptions = array();
  • 800   $div = $this->_extractOption('div', $options, false);
  • 801   unset($options['div']);

これで何も指定しなくても、inputメソッドにはdivがつかなくなりました。

複数チェックボックスの作成

inputメソッドのオプションで'type' => 'select'、'multiple' => 'checkbox'と指定します。

<?php

  • echo $this->Form->input('新宿' , array(
  •   'type' => 'select' ,
  •   'multiple'  =>  'checkbox',
  •   'options'   => array(1,2,3,4,)

));?>

//展開後

<label for="ShopHoge">Hoge</label>

<input type="hidden" name="data[Shop][hoge]" value="" id="ShopHoge" />

<div class="checkbox"><input type="checkbox" name="data[Shop][hoge]" value="0" id="ShopHoge0" /><label for="ShopHoge0">1</label></div>

<div class="checkbox"><input type="checkbox" name="data[Shop][hoge]"
value="1" id="ShopHoge1" /><label for="ShopHoge1">2</label></div>

<div class="checkbox"><input type="checkbox" name="data[Shop][hoge]" value="2" id="ShopHoge2" /><label for="ShopHoge2">3</label></div>

<div class="checkbox"><input type="checkbox" name="data[Shop][hoge]"
value="3" id="ShopHoge3" /><label for="ShopHoge3">4</label></div>

しかしまた個別でdivに囲まれます。オプションの 'div' => FALSEも効きません。無理矢理解決するなら以下の2つでしょうか。

  • ・諦めてCSSでレイアウト
  • とりあえずinline指定しておけば。コード的には微妙ですが…
  • ・先ほどもやった、form.phpの書き換え

ん〜2.0ではこの部分に変更があるのか気になります。