Laravel Eloquent 比较日期时间字段中的日期
Posted
技术标签:
【中文标题】Laravel Eloquent 比较日期时间字段中的日期【英文标题】:Laravel Eloquent compare date from datetime field 【发布时间】:2014-09-28 04:22:23 【问题描述】:我想通过一个表达式从一个表中获取所有的行:
table.date <= 2014-07-10
但如果该列包含日期时间,我们就说:
2014-07-10 12:00:00
但如果我这样做:
where('date', '<=', $date)
它不会得到该行。
我猜这是因为 $date = 2014-07-10 这使得 mysql 假设它是 2014-07-10 00:00:00。
在常规 MySQL 中我会这样做
where DATE(date) <= $date
使用 Laravel 的 Eloquent 的等价物是什么?
【问题讨论】:
【参考方案1】:如果您仍然想知道如何解决它。
我用
protected $dates = ['created_at', 'updated_at', 'aired'];
在我的模型和我做的地方
where('aired', '>=', time());
所以只需使用 unix 在哪里进行比较。
另一方面,在视图中,您必须使用日期对象。
【讨论】:
这是唯一对我有用的,因为我已经在 $dates 中定义了 :) 谢谢 @pixie_frigo 文档中的 $protected $dates 在哪里?【参考方案2】:这是我的逻辑: 如果您正在比较日期,那么您的方法应该是 whereDate,如果您比较完整的日期时间,那么您的方法将只在哪里:
$calendar_alert = DB::table('calendar_alerts')->whereDate('when', '=', now()->format('Y-m-d'))->where('when', '>', now()->format('H:i:s'))->get();
【讨论】:
【参考方案3】:您可以通过选择以下一种语法来获取日期“2016-07-14”或“2016-07-14”之前的所有记录:
->whereDate('date','=','2014-07-10')
->whereDate('date', '<=', '2014-07-10')
或者使用其他代码来获取动态日期
whereDate('date',$date)
【讨论】:
这似乎根本无法回答问题。 @SteveFromAccounting 在这种情况下,代码不适用于 Laravel 吗?可以发一下代码sn-ps吗?【参考方案4】:use Carbon\Carbon;
public function scopePublished($query)
$now = Carbon::now();
$date = Carbon::parse($now)->toDateString();
$time = Carbon::parse($now)->toTimeString();
return $query->whereDate('published_at', '<', $date)
->orWhere(function($query) use ($date, $time)
$query->whereDate('published_at', '=', $date)
->whereTime('published_at', '<=', $time);
);
【讨论】:
【参考方案5】:您是否考虑过使用:
where('date', '<', '2014-08-11')
您应该避免在 MySQL 中的索引列上使用 DATE()
函数,因为这会阻止引擎使用索引。
更新
由于似乎对DATE()
和索引的重要性存在一些分歧,我创建了一个fiddle 来展示差异,请参阅POSSIBLE KEYS
。
【讨论】:
为什么他应该避免在索引列上使用DATE()
?
这可能是一个解决方案,但看起来更像是一种 hack,而不是最佳实践。如果一个文件中包含 00:00:00 作为时间呢?
@almo,一旦你习惯了 MySQL 比较日期的方式,它就不会太糟糕了。这就像字符串比较; “2014-08-10 00:00:00”大于“2014-08-10”。
@Almo 你应该避免在索引列上使用 DATE() 因为它会阻止 MySQL 使用这个索引。如果可能,请使用比较运算符右侧的表达式。不,这是最佳实践,而不是 hack!
::whereRaw("DATE(date) <= '2014-08-10'")
。 @Arth他没有提到索引,所以我不知道它有什么毛病。正如你所说,@almo 2014-07-10
将被转换为 DATETIME
(2014-07-10 00:00:00
)。但是,您将DATE
与DATETIME
进行比较,您要么将DATETIME
转换为DATE
,要么将23:59:59
添加到$date
。【参考方案6】:
Laravel 4+ 为您提供这些方法:whereDay()
、whereMonth()
、whereYear()
(#3946) 和 whereDate()
(#6879)。
他们为您执行 SQL DATE()
工作,并管理 SQLite 的差异。
你的结果可以这样实现:
->whereDate('date', '<=', '2014-07-10')
有关更多示例,请参阅#3946 的第一条消息和此Laravel Daily article。
更新: 虽然上述方法很方便,但正如 Arth 所说,它在大型数据集上效率低下,因为必须对每条记录应用 DATE()
SQL 函数,从而丢弃可能的索引。
以下是一些进行比较的方法(但请阅读下面的注释):
->where('date', '<=', '2014-07-10 23:59:59')
->where('date', '<', '2014-07-11')
// '2014-07-11'
$dayAfter = (new DateTime('2014-07-10'))->modify('+1 day')->format('Y-m-d');
->where('date', '<', $dayAfter)
注意事项:
23:59:59 可以(暂时)因为 1 秒的精度,但请看这篇文章:23:59:59 is not the end of the day. No, really! 请记住“零日期”情况(“0000-00-00 00:00:00”)。尽管应该避免这些“零日期”,但它们是许多问题的根源。如果需要,最好使该字段可以为空。【讨论】:
同样,我建议不要使用这种方法,它会将列包装在DATE()
函数中,并且引擎无法在列上使用索引。
没问题!我对日期像字符串一样进行比较是错误的,它们只是被转换然后比较。 2014-07-11
将在比较之前隐式转换为 2014-07-11 00:00:00
,幸运的是,这与您的其他解释很好。
另外请注意,您可以愉快地使用WHERE date < :date + INTERVAL 1 DAY
,而不是在 php 中乱搞日期
确实是关于 MySQL INTERVAL
。不过,如果可能的话,我更喜欢在 PHP 端进行处理,而不是 MySQL 甚至 Apache。我厌倦了他们所有的微妙之处。
THAX ALOT:对我有用的地方我正在使用 laravel 7+【参考方案7】:
你可以用这个
whereDate('date', '=', $date)
如果您提供 whereDate 则仅比较日期时间字段中的日期。
【讨论】:
以上是关于Laravel Eloquent 比较日期时间字段中的日期的主要内容,如果未能解决你的问题,请参考以下文章
无法让 Laravel OrderBy 日期在 Eloquent 语句中工作
通过laravel Eloquent Model以dd / mm / yyyy插入日期格式
Laravel - 使用 eloquent 在开始日期和结束日期之间选择行