Laravel 中的 View Composer 該如何使用?
假設有一個網頁,這個網頁有一個區塊是 menubar (選單欄)。menubar 上面有許多連結,這些連結都是儲存在資料表 categories 中。
因為這個 menubar 會固定在網頁上方,這代表幾乎所有的 blade 模板都會 include 這個 menubar 的 blade。那麼要如何將連結資料從資料表 categories 撈取出來之後,正確傳給 blade 並顯示呢?
土法煉鋼的作法。是在每個 Controller 裡的每個方法中寫上一段,去撈取資料表 categories 的所有資料。
$categories = Category::all();
然後再將變數 $categories 傳給 view。
return view('index', ['categories' => $categories]);
在每個 Controller 加上這一段,才能確保不論到哪一頁,menubar 都能確實收到變數 $categories
。
並正確顯示 menubar 上的所有連結。
但在每個 Controller 都加上這一段,工程師才沒這麼勤勞
官方其實還有另外一種方法 View Share,可以直接將參數傳給所有的 blade。
但是你很有可能遇到在 migration 時候噴錯,詳情請參考此連結,這時我們可以考慮使用 View Composer,將變數傳給指定的 blade 來使用。
首先新增檔案 app/Http/View/Composers/CategoryComposer.php
。
<?php
namespace App\Http\View\Composers;
use App\Models\Category;
use Illuminate\View\View;
use Cache;
class CategoryComposer
{
// 設定用來依賴注入的變數
protected $category;
public function __construct(Category $category)
{
// 將 Category Model 依賴注入到 CategoryComposer
$this->category = $category;
}
public function compose(View $view)
{
// 取得所有分類並放入變數 categories
$categories = this->category->all();
// 將資料綁定至 blade 模板中
$view->with('categories', $categories);
}
}
上段程式碼中,依賴注入的對象是 Model,但官方文件在這裡選擇注入的對象是 Repository。一般來說大型專案會採用下面這種模式,以便於維護。
Model ←→ Repository ←→ Service ←→ Controller
但這個模式並非強求,也有人覺得使用這種模式反而讓程式碼不易閱讀
所以只要專案組員們討論後有共識即可。
然後 app/Providers/
底下新增一個檔案 ViewServiceProvider.php
,內容可以參考官方文件。
在 ViewServiceProvider.php
的 boot()
中新增一段程式碼。
use Illuminate\Support\Facades\View;
use App\Http\View\Composers\CategoryComposer;
public function boot()
{
// 將分類的資料綁定至 View 中
View::composer('layouts.menubar', CategoryComposer::class);
}
新增的 ViewServiceProvider.php
檔案,必須要在 config.php
中註冊才能使用。
'providers' => [
//視圖合成器
App\Providers\ViewServiceProvider::class,
]
這時,即使 Controller 沒有特地寫一段來傳遞參數 $categories
。
resources/views/layouts/menubar.blade.php
這個模板也能獲取 $categories
中的連結資料。