LoginSignup
0
1

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-09-14

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);
});
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1