WEBサービスにおいてフォームは必要不可欠な要素ですが、サービスを運営していると、色々な用途に対応させたフォームを作成しなければならないことがあります。PHPでWEBサービスを作成する際に使用されるフレームワークに、CakePHPというものがありまが、その機能の一つであるフォームヘルパーを利用すると、容易にフォームを作成することができます。
しかし、フォームヘルパーはお手軽なので、仕様を理解していないと意図したフォームが作成できず、無駄に時間を割いてしまうことがあります。そこでこの記事では、その例の一つとして、ラジオボタンのデフォルト値について私がハマった問題とその解決策を紹介したいと思います。
背景と問題点
ラジオボタンとは、フォームでよく見かける複数の選択肢の中から一項目だけ選択させることができるものですが、デフォルト値を設定することで、最初からどれかを選択させておくことができます。CakePHPでは、以下のように’defaut’ => ‘hogehoge’ とすることで、簡単に設定することができます。
$this->Form->radio('user_icon', $iconOption, ['default' => 'hogehoge']);
しかし、場合によってはデフォルト値を設定したくない場合もあるかと思います。例としては、ログイン中のユーザーであれば登録済みのデータ(名前、年齢、アイコンなど)を初めから設定しておき、そうでない場合は空にしておきたい、といった状況が考えられます。私は初め、以下のようなコードでこの条件に合うラジオボタンを生成しようとしていました。
$iconOption = [
'1' => 'アイコン1',
'2' => 'アイコン2',
'3' =>'アイコン3'
];
$this->Form->radio('user_icon', $iconOption, ['default' => $userIcon ?: false]);
〇表示されるフォーム
一件何の問題もないのですが、ここで何も選択しないままポストした場合、キーが存在しないため、このキーを使ってバリデーションチェックを行う際にエラーになってしまいます。
試行① とりあえず何かしらのデフォルト値を設定する
$this->Form->radio('user_icon', $iconOption, ['default' => !empty($userIcon) ?: 1]);
〇表示されるフォーム
こうすることで、ユーザーが登録したアイコン ($userIcon)がない場合は、オプションの一つ目を初めから選択させておくことができ、ポストした際にキーが存在しないという問題も解決できます。しかし、選択肢がアイコンの場合は問題ないと思いますが、これでは意図したフォームを作成できない場合もあります。
例えばアンケートなどで初めから何か選択されていた場合、ユーザーは何も入力せずに、初めから選択された項目のまま送信することが可能になってしまいます。これでは、ユーザーの直観的な回答を求めているにもかかわらず、有効な回答が得られないかもしれません。
ただし、上記の例や、性別を選ばせるような場合、何かしらのデフォルト値を設定しておくのには有効な解決策と言えるかもしれません。
ちなみに、コントローラー側で以下のようにデフォルト値を設定することもできますが、項目数が増えれば増えるほどコードも長くなってしまうので、コントローラー内の記述が煩雑になってしまいます。
$this->data['user_icon'] = $userIcon;
試行② hiddenFieldをtrueにしてみる
次に、hiddenFieldをtrueにすることで、hiddenフィールドを生成し、値がなくてもキーが存在するようにしてみました。
$this->Form->radio('user_icon', $iconOption, ['default' => !empty($userIcon) ?: false, 'hiddenField' => true]);
〇表示結果
表示結果を見てもわかるように、hiddenが生成されていません。そもそもCakePHPの場合、ラジオではhiddenFieldはデフォルトでtrueになるはずなので、根本的に何か間違っているようです。
試行③ 無理やりhiddenを生成する
hiddenが生成されないので、今度は無理やり生成してみることにしました。
$this->Form->hidden('user_icon');
〇表示結果
これでキーが存在しないという上記の問題は解決されますが、ラジオボタンを使うたびにこれを記述するのも、何だかすっきりしません。
解決策 CakePHPのラジオボタンでhiddenが生成される条件を確認
ここでやっと、CakePHPの仕様を確認してみることにしました。
if($hiddenField){
if(!isset($value) || $value === ''){
$hidden = $this->hidden($fieldName, array(
'id' => $attributes['id'].'_', 'value' => '', 'name' => $attributes['name']
));
}
}
CakePHPでは、hiddenFieldがtrueの場合(上述のように、ラジオの場合はデフォルトでtrue)、$valueがセットされていないか、空文字の時にhiddenが生成される仕様になっていました。よって、コードを以下のように変更します。
$this->Form->radio('user_icon', $iconOption, ['default' => !empty($userIcon) ?: '']);
〇表示結果
これで無事にhiddenが生成され、意図したラジオボタンを作成することができました。