- 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のまま。
無事に希望通りのデータが取得できました。