Help us understand the problem. What is going on with this article?

CakePHP3 ORMのWHERE句で、date_formatで指定した "Y" が "y" になってしまう

TL;DR

  • DATE_FORMATで %Y を使用する場合は、以下を参考にする
    • where句でコールバック関数とクロージャーを使用し、eqメソッドを使用する
$createdFormat = $query->func()->date_format([
    'created'    => 'identifier',
    "'%Y-%m-%d'" => 'literal'
]);
$query->where(function ($exp) use ($createdFormat, $created) {
    return $exp->eq($createdFormat, $created);
});

前提

  • PHP
    • 7.3.11
  • CakePHP
    • v3.6.14

事象

1.
ORM: $query->where(["DATE_FORMAT(created, '%Y-%c') = " => $date])
SQL: WHERE DATE_FORMAT(created, '%y-%c') = :c0
################
2.
ORM: $query->where(["DATE_FORMAT(created, '%Y-%c') = ${date}"])
SQL: WHERE DATE_FORMAT(created, '%Y-%c') = 2020-8)
  • 上記の通り、連想配列によるデータの渡し方では、発行されるSQLのフォーマットが、Yy になってしまう
  • 変数展開による渡し方では、発行されるSQLのフォーマットは、Y のまま

原因

  • 巡りめぐってQueryExpression::_parseCondition()を参照し、そこでstrtolowerを行ってるため
  • 以下対象コードの一部抜粋
    protected function _parseCondition($field, $value)
    {
        $operator = '=';
        $expression = $field;
        $parts = explode(' ', trim($field), 2);

        if (count($parts) > 1) {
            list($expression, $operator) = $parts;
        }

        $type = $this->getTypeMap()->type($expression);
        $operator = strtolower(trim($operator));

        ...

        return new Comparison($expression, $value, $type, $operator);
    }

対策

  1. date_formatで指定したいカラムを、別でフォーマット化する
  2. WHERE句でコールバック関数とeqメソッドを使って条件に追加する
$createdFormat = $query->func()->date_format([
    'created'    => 'identifier',
    "'%Y-%m-%d'" => 'literal'
]);
$query->where(function ($exp) use ($createdFormat, $created) {
    return $exp->eq($createdFormat, $created);
});
tatsuo-iriyama
Web Engineer|96'|高卒|前職:溶接工|2019-01〜ユアマイスター株式会社|
yourmystar
サービス産業のIT化プラットフォーム「ユアマイスター」と大切なものをもっと大切にするメディア「ユアマイスター スタイル」を運営するスタートアップです。
http://corp.yourmystar.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした