如何根据动态列分钟计算 Laravel Eloquent 中不同的日期时间

How to calculate date time different in Laravel Eloquent based on dynamic column minutes

我正在尝试基于两个数据库和列进行查询。

$model->where('response_time', '<=', Carbon::now()->subMinutes(\DB::raw('anotherTable.created_at'))->diffInMinutes(Carbon::now()))

response_time包含一个整数分钟,即:15

如果 anotherTable.created_at - response_time(即小于 15 分钟)小于当前时间,return 行。

我已经尝试过上述方法,但我运气不好,也不知道如何调试我的查询。任何帮助表示赞赏。

应该通过的示例查询和return它的行(超过 1 分钟):

response_time 15

anotherTable.created_at 21-03-2022 13:40:00

当前时间:21-03-2022 13:56:00

试一试:)

$model->where('response_time', '<=', Carbon::now()
    ->diffInMinutes(\DB::raw('anotherTable.created_at')));

您不能依赖碳函数中使用的 table 值。

相反,您必须在数据库上进行计算。

下面的代码理论上应该可以工作,但我还没有测试过。

所有需要数据库数据的计算都在数据库上完成。

Carbon 仅用于将条件值传递给它。

$model->where(
    DB::raw('DATE_SUB(anotherTable.created_at, INTERVAL response_time MINUTE)'), '<=', Carbon::now()
);

希望对您有所帮助

Carbon::parse('21-03-2022 13:40:00')->diffInMinutes(new DateTime)

或者

Carbon::parse('21-03-2022 13:40:00')->diffInMinutes(Carbon::now())

在你的情况下使用这个:

Carbon::parse(DB::raw('anotherTable.created_at'))->diffInMinutes(Carbon::now())

为什么 Carbon 不工作

Carbon 无法在 PHP 端 ($model->where()) 生成查询期间从数据库中检索值。 Carbon 将在向数据库发出查询之前立即对 'anotherTable.created_at'string 值执行。相当于:

$offset = Carbon::now()
    ->subMinutes('anotherTable.created_at')
    ->diffInMinutes(Carbon::now()); // 0 

$model->where('response_time', '<=', $offset); // WHERE responst_time <= 0

碳过程分解

Carbon\Traits\Date::__call()用于从方法名解析动作和单位为subminutes.
该过程有条件地调用 Carbon\Traits\Units::subUnit('minute', 'anotherTable.created_at') [sic] which calls Carbon\Traits\Units::addUnit($unit, -$value, $overflow) [sic].

-$value 最终由 PHP 处理为 -'anotherTable.created_at' 导致 0 就像您调用 Carbon::now()->subMinutes(0).

如果 Carbon 在为 $value 参数提供 string 时抛出 TypeError 异常,而不是预期的 int。但是,Carbon\Traits\Units::subUnit($unit, $value)$value 参数不是 type-hinted.


MySQL分辨率

不使用 Carbon,而是使用 MySQL TIMESTAMPDIFF() 函数在查询中生成 anotherTable.created_atNOW() 之间的分钟差值。

db<>fiddle Example

假设在查询中添加 anotherTable JOIN

$model->where(
    'response_time', '<=',  DB::raw('TIMESTAMPDIFF(MINUTE, anotherTable.created_at, NOW())')
);