- Datetimeで保存されているデータを
DATE_FORMAT
でY-m-d
の形式を条件として絞り込みたい。 - 難しいことではないのですが、少しはまったので備忘録。
#CakePHP2とCakePHP3での書き方の違い
##CakePHP2の場合
CakePHP2まではconditionsに思ったままの事を書けばできます。
$conditions = ["DATE_FORMAT(created, '%Y-%m-%d')" => 'CURRENT_DATE()'];
これでCURRENT_DATE()
で絞り込んだデータを取得することができます。
##CakePHP3の場合
CakePHP3でも似たようなものだと思っていたので下記の様に記述。
(ただし=
をつけないとエラーが発生するので注意)
$query->where([
"DATE_FORMAT(created, '%Y-%m-%d') =" => $query->func()->now('date')
])
CURRENT_DATE()
をCakePHP3っぽく$query->func()->now('date')
と記述。
#問題
一見上記で問題がないように動作していたのですが、データがうまく取れていないことが発覚。
出力されたSQLのWHERE
を確認してみると、
WHERE
DATE_FORMAT(created, '%y-%m-%d') = (
CURRENT_DATE()
)
%Y
で指定したはずが%y
になっています。
……なぜ。
#対策
1. func()->date_format()を使う
そのまま記述するのが原因のようなのでfunc()
を使用してDATE_FORMAT
を記述してみます。
$created = $query->func()->date_format([
'created' => 'identifier',
"'%Y-%m-%d'" => 'literal'
]);
$query->where([
$created => $query->func()->now('date')
]);
Illegal offset type……
条件に使用する想定ではないのでしょうか、怒られます。
でも$query->func()->now('date')
も使いたい。(逆にしてみたけどやはり怒られる)
2. よりCakePHP3っぽい書き方にする
func()->date_format()
を使用しつつ、よりCakePHP3の記述に近づけてみます。
$created = $query->func()->date_format([
'created' => 'identifier',
"'%Y-%m-%d'" => 'literal'
]);
$today = $query->func()->now('date');
$query->where(function ($exp) use ($created, $today) {
return $exp->eq($created, $today);
});
発行されたSQLを確認しても%Y
のまま。
無事に希望通りのデータが取得できました。