Laravel 提供兩種機制在多個視圖間共享資料:全域共享 (view()->share()) 與 視圖 Composer (view()->composer())。前者適用於所有視圖都需要的靜態資料(如站點名稱),後者適用於需邏輯運算、依賴注入的動態資料(如登入使用者資訊、購物車數量)。本文詳細說明兩者用法與差異。
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider {
public function boot() {
// 所有視圖皆可直接使用 $sitename 變數
view()->share('sitename', 'Laravel 學院');
}
public function register() { /* ... */ }
}
?>
// routes/web.php
Route::get('hello', function () { return view('hello'); });
Route::get('home', function () { return view('home'); });
{{-- resources/views/hello.blade.php --}}
歡迎來到 {{ $sitename }}!
{{-- resources/views/home.blade.php --}}
{{ $sitename }} 首頁
訪問 /hello 與 /home 均正常輸出「Laravel 學院」。
public function boot() {
view()->share('sitename', 'Laravel 學院');
// 僅 hello 視圖注入 $user 變數
view()->composer('hello', function ($view) {
$view->with('user', [
'name' => 'test',
'avatar' => '/path/to/test.jpg'
]);
});
}
歡迎來到 {{ $sitename }}!
<h3>使用者資訊</h3>
使用者名:{{ $user['name'] }}<br>
使用者頭像:{{ $user['avatar'] }}
訪問 /hello 顯示使用者資訊;/home 不受影響。
// 陣列指定多個視圖
view()->composer(['hello', 'home'], function ($view) {
$view->with('user', ['name' => 'test', 'avatar' => '/path/to/test.jpg']);
});
// 所有視圖皆注入
view()->composer('*', function ($view) {
$view->with('user', ['name' => 'test', 'avatar' => '/path/to/test.jpg']);
});
<?php
namespace App\Http\ViewComposers;
use Illuminate\View\View;
use App\Repositories\UserRepository;
class ProfileComposer {
protected $users;
public function __construct(UserRepository $users) {
$this->users = $users;
}
public function compose(View $view) {
$view->with('profile', $this->users->getAuthProfile());
}
}
public function boot() {
view()->composer('profile', 'App\Http\ViewComposers\ProfileComposer');
// 或多視圖
view()->composer(['profile', 'dashboard'], 'App\Http\ViewComposers\ProfileComposer');
}
| 特性 | view()->share() | view()->composer() |
|---|---|---|
| 適用場景 | 靜態、全域、不變資料 | 動態、需邏輯運算、特定視圖 |
| 資料來源 | 直接給值 | 閉包/類別方法運算產生 |
| 依賴注入 | 不支援 | 支援 (類別式 Composer) |
| 作用範圍 | 所有視圖 | 指定視圖/通配符 |
| 效能影響 | 極小 | 視邏輯複雜度而定 |
share()。composer('*') 或針對布局視圖 composer('layouts.app')。composer('profile') 類別式,利用 DI 獲取 Repository。Cache::remember())。view()->share() 適合「一次設定、到處可用」的靜態資料;view()->composer() 適合「按需運算、精準注入」的動態資料。善用兩者結合,可保持控制器精簡、視圖資料來源清晰、效能可控。