如何比较两个日期的月份部分?

How to compare the month parts of two dates?

我正在尝试查询当前月份,这是我的查询:

 $clients = $this->Clients;
    $query = $clients->find();

    if($this->Auth->user('role') !== 'admin'){
        $query->where(['user_id =' => $this->Auth->user('id')]);
        $query->where(['MONTH(dob) = ' => 'EXTRACT(month FROM (NOW()))']);

        $query->order(['dob' => 'ASC']);

    }

它 returns 0 条记录(我的字段是日期类型),但是 phpmyadmin 中的这个查询有效:

SELECT * FROM `clients` WHERE MONTH(dob) = EXTRACT(month FROM (NOW()))

我做错了什么?

只需查看实际生成的查询(查看您的 DBMS 查询日志,或尝试 DebugKit),它看起来会有所不同,因为 key => value 条件集中的右侧值是受 parameter-binding/casting/quoting/escaping 约束。在你的情况下,它将被视为一个字符串,所以条件最终看起来像:

WHERE MONTH(dob) = 'EXTRACT(month FROM (NOW()))'

那当然不会匹配任何东西。

您可以将整个 SQL 片段作为单个数组值或作为表达式对象传递,这样它会按原样插入到查询中(不要那样插入用户值,那样会创建一个 SQL 注入漏洞!),但我建议改用可移植函数表达式。

CakePHP 附带 EXTRACTNOW 的函数表达式,因此您可以简单地执行以下操作:

use Cake\Database\Expression\IdentifierExpression;
use Cake\Database\Expression\QueryExpression;
use Cake\ORM\Query;

// ...

$query->where(function (QueryExpression $exp, Query $query) {
    return $exp->eq(
        $query->func()->extract('MONTH', new IdentifierExpression('dob')),
        $query->func()->extract('MONTH', $query->func()->now())
    );
});

看起来有点复杂,但它是值得的,它可以跨 DBMS 移植并且 auto-quoting 兼容。生成的 SQL 看起来像

WHERE EXTRACT(MONTH FROM (dob)) = (EXTRACT(MONTH FROM (NOW())))

另见