Laravel 5.4 入門系列 10.文章歸檔

首先,要實現的是按照日期來統計文章,原始的 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}}&nbsp{{$archive->year}}</a></li>
      @endforeach
    </ol>
  </div>

用戶點擊某個月份的時候,向後臺傳入 monthyear 參數,所以 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


相關文章
相關標籤/搜索