首先,要實現的是按照日期來統計文章,原始的 SQL 以下:php
select year(created_at) year, monthname(created_at) month, count(*) published from posts group by year, month order by min(created_at) desc;
將其轉化爲 Eloquent Model
:html
/app/Http/Controllers/PostsController.php use App\Post; public function index() { $archives = Post::selectRaw('year(created_at) year, monthname(created_at) month, count(*) published') ->groupBy('year','month') ->orderByRaw('min(created_at) desc') ->get(); $posts = Post::latest()->get(); return view('posts.index',compact('posts','archives')); }
視圖中顯示對應的文章歸檔:laravel
/resources/views/layouts/siderbar.blade.php <div class="sidebar-module"> <h4>Archives</h4> <ol class="list-unstyled"> @foreach ($archives as $archive) <li><a href="/posts/?month={{$archive->month}}&&year={{$archive->year}}">{{$archive->month}} {{$archive->year}}</a></li> @endforeach </ol> </div>
用戶點擊某個月份的時候,向後臺傳入 month
和 year
參數,所以 index
方法還須要根據參數類型來進行選擇:sql
/app/Http/Controllers/PostsController.php use Carbon\Carbon; public function index() { $archives = Post::selectRaw('year(created_at) year, monthname(created_at) month, count(*) published')->groupBy('year','month')->orderByRaw('min(created_at) desc')->get(); $posts = Post::latest(); if ($month = request('month')) { $posts->whereMonth('created_at',Carbon::parse($month)->month); } if ($year = request('year')) { $posts->whereYear('created_at',$year); } $posts = $posts->get(); return view('posts.index',compact('posts','archives')); }
這裏使用了 Laravel 提供的 whereDate
系列方法,同時,月份用 Carbon
進行轉換。數據庫
將上述的一系列查詢進行封裝:app
/app/Http/Controllers/PostsController.php public function index() { $archives = Post::archives(); $posts = Post::latest() ->filter(request(['year','month'])) ->get(); return view('posts.index',compact('posts','archives')); }
模型:composer
/app/Post.php use Carbon\Carbon; public function scopeFilter($query, $value) { if ($month = $value['month']) { $query->whereMonth('created_at', Carbon::parse($month)->month); } if ($year = $value['year']) { $query->whereYear('created_at', $year); } } 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(); }
到了這一步,咱們基本上實現了文章歸檔的功能。可是有一個問題,文章歸檔實際上包括在通用視圖中,這就意味着,網站的全部請求都須要返回 $archives
,不然就會報錯。一種作法就是在不一樣方法下都調用 archives()
方法來返回數據。固然,更爲簡單的方法就是使用「視圖共享數據」功能。操做以下:ide
/app/Providers/AppServiceProvider.php public function boot() { Schema::defaultStringLength(191); view()->composer('layouts.siderbar',function($view){ $view->with('archives',\App\Post::archives()); }); }
該服務提供者包含兩個方法:register()
,用來綁定 IOC 容器(先忽略),綁定完以後,咱們就能夠在 boot
裏面定義咱們想要實現的功能了,在該例中,咱們註冊了 layouts.siderbar
視圖,並傳遞給視圖 archives
變量。post