如何在Laravel 5.1中从数据库表的created_at属性中选择年份和月份?

31

我的问题是,我想从数据库表中按年份和月份获取created_at属性的数据。我尝试过的代码是:

$post= Mjblog::select(DB::raw('YEAR(created_at) year, MONTH(created_at) month'));
$posts_by_y_m = $post->where('created_at',$post)->get();

你的意思是返回结果应包含给定 Mjblog 模型的所有年份和月份,如果是的话,那么为什么要这样做:$post->where('created_at',$post)->get(); - Mustafa Ehsan Alokozay
请稍微澄清一下你的问题。 - Mustafa Ehsan Alokozay
我的确切需求是,当我点击存档月份和年份时,需要显示数据库表的内容,其中有一个created_at日期字段。 - Pawan Dongol
3个回答

97

查询构造器中提供了日期助手:

$post = Mjblog::whereYear('created_at', '=', $year)
              ->whereMonth('created_at', '=', $month)
              ->get();

2
你也可以使用 ->whereMonth('created_at', $month)。两种方法都可以。 - Samir Mammadhasanov

12

绩效评估

虽然被接受的答案可能解决了OP的问题,但从数据库性能的角度来看,这并不是最佳解决方案。因为当应用whereYear()whereMonth()辅助函数查询记录时,它会使查询变得SARGable。这意味着如果比较的列created_at在数据库中有索引,则在搜索数据时将忽略此索引。请参见什么使SQL语句sargable?

考虑以下表达式

$posts = Mjblog::whereYear('created_at', '=', $year)
               ->whereMonth('created_at', '=', $month)
               ->get();

生成的查询将会像这样

select * 
from mjblog 
where year(`created_at`) = :year 
  and month(`created_at`) = :month

上面的查询可以明显看出是不可搜索的,因为在created_at上应用了year()month()函数,从而产生了一个非索引值。
为了使它成为可搜索表达式,最好在比较索引列时定义确切/范围的值。就像对于OP,范围可以从月份和年份的值中派生出来。
$year = 2000;
$month = 2;
$date = \Carbon\Carbon::parse($year."-".$month."-01"); // universal truth month's first day is 1
$start = $date->startOfMonth()->format('Y-m-d H:i:s'); // 2000-02-01 00:00:00
$end = $date->endOfMonth()->format('Y-m-d H:i:s'); // 2000-02-29 23:59:59

现在,可搜索的表达式可以写成:


select * 
from mjblog 
where created_at between :start and :end

或者

select * 
from mjblog 
where created_at >= :start 
  and created_at <= :end

在查询构建器中,它可以表示为
$posts = Mjblog::whereBetween('created_at', [$start, $end])
               ->get();

或者

$posts = Mjblog::where('created_at', '>=', $start)
               ->where('created_at', '<=', $end)
               ->get();

另一篇有用的文章,突出了非SARGable谓词和反模式的缺点。


你是在暗示这个解决方案的查询速度比已接受的解决方案快很多吗? - Toni Tegar Sahidi
1
如果created_at是索引列,那么这种方法会利用添加的索引,而另一种方法则会忽略它,因为查询将应用于year()和month()函数,从而产生与索引值不同的新值。 - M Khalid Junaid

9

如果您想从一个Mjblog实例中获取年份和月份,可以按照以下方式访问:

$year = $post->created_at->year;
$month = $post->created_at->month;

阅读有关Carbon\Carbon 获取器文档的更多信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接