CakePHP FormHelper::datetime で秒までセレクトしたい

cake
CakePHP も日々進化してくれて、色々機能も充実してきて嬉しい限りなのですが、ちょこちょこと細かいカスタマイズは当然必要。というわけで、FormHelper の日時セレクトボックスが秒非対応(CakePHP 2.3にて)なので、自分で追加したときのメモです。因みに、ケーキつながりで、写真のガトーショコラも自作です。

FormHelper は秒のセレクタは表示してくれない

FormHelper::input のフィールドに、DB側で DATETIME にしているカラムを指定すると、内部で FormHelper::datetime がコールされるのですが、ここでセレクタの中身となる OPTION タグを生成している部分を見ても、秒セレクタを生成しているロジックが見当たりませんでした。

http://api.cakephp.org/2.3/source-class-FormHelper.html

という事は、オプション設定をいじって表示してもらおう♪ なんて甘い考えは通用しないらしく、仕方ないので自作します。本当は秒まで表示してくれちゃう、’second’=>true みたいな素敵オプションがあると期待していたのに・・・。

FormHelper で分まで生成して後ろにこっそり秒を付け足す

フレームワークを使って開発するときは極力自分で書かないを貫き、あくまでも「秒」だけを自作します。

【前提】

  • DB 上は mymodel テーブル / DATETIME 型 / time というカラムが操作対象
  • CakePHP デフォルトのスタイルシートを使用
  • デフォルトは2013年10月13日15時15分15秒は 13-October-2013 03:15 pm と表示されるところ、2013-10-13 15:15:15 と表示する。
// 分までは Form->input で普通に表示
echo $this->Form->input('time', array(
'dateFormat'=>'YMD', // (1)
'monthNames'=>false, // (2)
'timeFormat'=>'24', // (3)
'div'=>array('style'=>'float:left'), // (4)
));

$secondOptions = array();
for ($i=0; $i<60; $i++) { // 00~59秒の選択肢をつくる
$secondOptions[sprintf('%02d', $i)] = sprintf('%02d', $i);
}
echo ':' . $this->Form->select('Mymodel.time.sec', $secondOptions, array( // ★
'div'=>false, // (5)
<em id="__mceDel"><em id="__mceDel"><em id="__mceDel">'empty'=>false, // (6)</em></em></em>
<em id="__mceDel"><em id="__mceDel"><em id="__mceDel"><em id="__mceDel">'value'=>date_create($this->request->data['Mymodel']['time'])->format('s'), // (7)
));


コード解説です。

(1) デフォルトは 13-October-2013 と表示されるところ 2013-10-13 として表示します。
(2) October じゃなくて 10 と表示します。
(3) デフォルトで時間が 03 pm と表示されるところ、15 と表示します。
(4) このセレクタを囲むDIVにスタイルを適用します。こうすることで、次に付けたす「秒」のセレクタが隣りに来てくれます。CakePHPデフォルトでは、FormHelper が表示する input タグはそれぞれ個別のDIVで囲まれ、その DIV は display:block です。なので、デフォルトのままだと、これから付け足す「秒」セレクタが次行に表示されてしまいます。
(5) FormHelper が書き出すセレクタを DIV で囲まないようにします。
(6) 空白を許可せず、必ず00~59のどれかが選択されるようにします。
(7) ADD時は00となりますが、EDIT画面ではDBに格納されている秒が初期状態で選択されるようにします。

★ の行で指定している第一引数であるフィールド名 ‘sec’ がキーです。

モデル名.フィールド名.sec という名前を指定しておくと、これだけで内部で「秒」部分として連結してくれました♪ 本来なら、勝手に付け足した「秒」セレクタなので、コントローラで $this->request->data[‘Mymodel’][‘time’][‘sec’] を time フィールドの「秒」部分として連結するのも自作するつもりでいたのに、何故かそっちは勝手にやってくれました(笑) FormHelper 側だけ対応してくれないのは不思議です。何か意図的に「秒」を抜いているのであれば、ある日のアップデートでコントローラ側で sec を秒部分として連結してくれる実装も削除されちゃう可能性アリですのでご注意を。