Posted at

CakePHP3でDB取得時のDateTime型をフォーマット変換

More than 1 year has passed since last update.

やりたかったことは至極単純。

MySQLのDateTime型で定義されている項目を、フォーマット変換してCSV出力させること。

CakePHP3初心者な事もあり、解決まで少々時間を要してしまったので、自分同様にCakePHP3初心者が同じ轍を踏まないようメモ書きを残しておきます。


CakePHP3のクエリビルダでDateTime型を取得

日時/日付のSQL取得方法は、各データベースによって仕様が異なる。

例えばこんな感じ↓↓↓

・Oracleの場合、SELECT TO_CHAR(date,'yyyy/mm/dd') FROM dual;

・MySQLの場合、SELECT DATE_FORMAT(now(),'%Y/%m/%d');

・postgreSQLの場合、SELECT TO_CHAR(current_timestamp, 'yyyy/mm/dd');

今回MySQL使ってたので、CakePHP3のクエリビルダでDATE_FORMATを使う手段をググッてみると、func()->date_format()で実現可能なことが分かった。


filename.rb

$created = $query->func()->date_format([

'created' => 'identifier',
"'%Y%m%d %k%i%s'" => 'literal'
]);
$modified = $query->func()->date_format([
'$modified' => 'identifier',
"'%Y%m%d %k%i%s'" => 'literal'
]);

コレをselectで指定すれば、確かにSQL上ではDATE_FORMATが指定されていたけど、どうにも返却される値が上手くフォーマットされていなかった。


filename.rb

id,作成日時,更新日時

1,"3/8/17, 5:08 PM","3/8/17, 5:08 PM"


CakePHP3でのdatetime型について

返却された配列をデバッグしてみると原因が分かった。


filename.rb

[0] => Array (

[id] => 1
[created] => Cake\I18n\FrozenTime Object (
[time] => 2017-03-08T17:08:52+00:00
[timezone] => UTC
[fixedNowTime] =>
)
[modified] => Cake\I18n\FrozenTime Object (
[time] => 2017-03-08T17:08:56+00:00
[timezone] => UTC
[fixedNowTime] =>
)
)

FrozenTimeという見慣れぬObjectで返されているけど、どうやらdatetime型はCake\I18n\FrozenTimeで返されるらしい。ちなみにdate型は3.1迄はCake\I18n\FrozenDate、3.2からはCake\I18n\FrozenTimeになっている。

なので取得された配列(またはJSON)に対して、フォーマット変換することで解決しました。


filename.rb

$created = $data['created']->i18nFormat('YYYY/MM/dd HH:mm:ss');


ちゃんと公式HP確認してたら、何てこと無いんだろうけどね...