I am trying to make an archive with Laravel where I can store written articles. I want this to have a structure like:
- Today
- Article 1
- This week
- Article 2
- article 3
- This month
- Article 4
- This year
- Article 4
And when there are no articles in, for example "Today", the title "Today" is not shown. Same for any other category.
I managed to make an archive where I could store articles within a specific format, like per year:
$archives = Article::all()->groupBy(function($date) {
return Carbon::parse($date->created_at)->format('Y');
});
but is it possible to achive the list I gave above with some changes to the code I have now or with some other code?
I think using MySQL, we can make it fairly elegant (although it does require a DB::raw()
). Also it's pretty easy to make changes to.
$groupSelect =
"CASE
WHEN DAYOFYEAR(created_at) = DAYOFYEAR(CURDATE()) THEN 'Today'
WHEN WEEKOFYEAR(created_at) = WEEKOFYEAR(CURDATE()) THEN 'This Week'
WHEN DATE_FORMAT(created_at, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m') THEN 'This Month'
WHEN YEAR(created_at) = YEAR(CURDATE()) THEN 'This Year'
ELSE 'Super Duper Long Time Ago'
END AS theGroup";
$archives = Article::select('*')->addSelect(DB::raw($groupSelect))->get()->groupBy(function($article) {
return $article->theGroup;
});
If you don't like the raw SQL you can add a function to your Article
model which will read the date and determine if it's Today, This Week, This Month, or This Year and returns that string...
public function getDiffForArchive()
{
if ( strtotime($this->attributes['created_at']) > strtotime('-1 day')) {
return 'Today';
} else if (...) { // Continue on with above logic.
return '...';
}
}
Then in your callback it's as simple as...
return $article->getDiffForArchive();
I've updated the SQL because I think it's close to what you want and also needed to start with select('*)
on your query builder, otherwise it will only select the theGroup
. It works now though, I've tested it.