sfWidgetFormSelectCheckbox, sfWidgetFormSelectRadioでchoicesのvalue値(label値ではなく)としてマルチバイト文字列を使うと、いくつかの選択肢が表示されなくなる現象がありました。
原因としては、inputタグを作るとき(render?)にinputタグのid値をユニークなキーとして使うらしく、そのid値はnameとvalueを「_」で繋いで作るんだけど、sfWidgetForm内でマルチバイト文字列(まぁ日本語の文字列)は「_」に変更されてしまうので、偶々複数のchoicesのvalue値の中に文字列長が同じのがあると、1つにまとまってしまうみたい。
長々と文章で説明するより実例のほうがわかりやすいかな。
$choices = array("ほげ"=>"ほげ", "ふが"=>"ふが");
をcheckboxやradioのchoicesとして指定すると、出力は
checkboxなら □ふが <input type="checkbox" name="check" value="ふが" id="check___" /> ふが
radioなら ○ふが <input type="radio" name="radio" value="ふが" id="radio___" />
のみになります。つまり最後の1個だけ。
で、これを回避するためにはid値の生成メソッド=sfWidgetForm::generateId()を下記のように変更してみました。
/lib/vender/symfony/lib/widget/sfWidgetForm.class.php
255行目〜オリジナル
// remove illegal characters
$name = preg_replace(array('/^[^A-Za-z]+/', '/[^A-Za-z0-9¥:_¥.¥-]/'), array('', '_'), $name);
255行目〜私の修正版
// remove illegal characters
//$name = preg_replace(array('/^[^A-Za-z]+/', '/[^A-Za-z0-9¥:_¥.¥-]/'), array('', '_'), $name);
$name = preg_replace('/^[^A-Za-z]+/', '', $name);
if(preg_match('/[^A-Za-z0-9¥:_¥.¥-]/', $name)>0)
{
$name = md5($name);
}
一見してわかるとおりマルチバイト文字を「_」×文字数に置換してしまうのではなく、マルチバイト文字列を含むname + _ + value をmd5ハッシュ化してしまっただけです。
デメリットはinputのid値を使ってCSSでデザインを指定したいときには厳しい(出力されたinputタグをみて頑張って><)ことぐらい?
まぁ個々のinputにデザイン決めたいぐらいの時はchoicesのkey(value値として渡す値)をアスキー文字だけにして使ってください。
今回の私の案件ように、運営者が自分でフォームの選択肢を編集する(しかも、運営者は、言語ファイル未アップでtitle, bodyとフォームのラベルが表示されたら「プログラムのコードが出ってます!!」と泡食って連絡してくるぐらい英語オンチ)とか、そういう特殊な状況じゃなければ多分使わないと思いますが。
#そういえば、mysqlのenumってマルチバイト文字使えたっけ。enumに日本語文字列を指定して、doctrineのschemaからフォームを自動生成させたらどうなるんだろう。そういう時この修正方法が生きるかも???誰か人柱お願いします(笑)
何年ぶりにsymfony記事を書いたんだろう、自分…。