How to create Archive block of the content type

  • Posted on: 11 December 2019
  • By: stillfinder

Let's say we have a Post model and we want to create an Archive block. Something like this:

Archive
- December 2019
- November 2019

First of all we need to add archives function to our model:

public static function archives()
    {
        return static::selectRaw('year(created_at) year, monthname(created_at) month, count(*) published')
            ->groupBy('year', 'month')
            ->orderByRaw('min(created_at) desc')
            ->get()
            ->toArray();
    }

Then add to our boot method of AppServiceProvider the next:

View::composer('web.partials.archives', function ($view) {
    $view->with('archives', Post::archives());
});

And finally, something like that to our blade template:

@foreach($archives as $stats)
    <li>
        <a href="/?month={{ $stats['month'] }}&year={{ $stats['year'] }}">{{ $stats['month'] . ' ' . $stats['year'] }}</a>
    </li>
@endforeach

After that, we can change the index method in our controller to filter by the provided month / year values. For example:

public function index(Request $request)
    {
        $posts = Post::latest()
            ->filterByDate(request(['month', 'year']))
            ->paginate(10);
 
        return view('web.posts.index', compact('posts'));
    }

Post model:

    public function scopeFilterByDate($query, $filters)
    {
        if (isset($filters['month'])) {
            $query->whereMonth('created_at', Carbon::parse($filters['month'])->month);
        }
 
        if (isset($filters['year'])) {
            $query->whereYear('created_at', $filters['year']);
        }
    }

BTW, if you are using pagination, you should add pagination links like below. Otherwise the month/year parameters will be replaced by the pagination query parameter

{{ $posts->appends(request()->input())->links() }}