上文通過字符串拼接實現主題切換,但模板內 @extends('layout.app') 仍需硬編碼路徑,維護成本高。本文介紹 Laravel 內置 View::addNamespace() 機制,實現主題級命名空間隔離,徹底解耦模板引用。
Laravel 允許為視圖註冊命名空間,語法:View::make('namespace::view.path')。註冊方式:
View::addNamespace('default', resource_path('views/default'));
View::addNamespace('blue', resource_path('views/blue'));
View::addNamespace('red', resource_path('views/red'));
調用時:View::make('blue::index.index')。
期望效果:設置默認命名空間後,直接 View::make('index.index') 即可自動解析到當前主題。
Laravel 並未提供 setDefaultNamespace 方法,但可通過 服務提供者 在請求生命周期早期動態綁定:
// App\Providers\ThemeServiceProvider.php
public function boot() {
$theme = Config::get('app.theme', 'default'); // 或從 DB/Session 讀取
$path = resource_path("views/{$theme}");
// 1. 註冊當前主題命名空間(別名 'theme')
View::addNamespace('theme', $path);
// 2. 將 'theme' 設為默認查找順序最優先
// 原理:View Finder 內部 $hints 數組決定查找優先級
$finder = View::getFinder();
$hints = $finder->getHints();
array_unshift($hints, 'theme'); // 插到最前面
$finder->setHints($hints);
}
模板中直接寫:
{{-- resources/views/blue/index/index.blade.php --}}
@extends('layout.app') {{-- 自動解析為 theme::layout.app --}}
@section('content')
當前主題:{{ config('app.theme') }}
@endsection
控制器無感調用:return View::make('index.index'); 即可渲染 blue/index/index.blade.php。
default 主題,其他主題通過 @extends('default::layout.app') 顯式繼承。app.theme 配置值,前端即時生效。users.theme 欄位,登入後寫入 Session。theme:publish 一鍵複製默認主題作為新主題骨架。view:clear 清理編譯緩存,確保切換即時生效。此方案利用框架核心機制,零 Hack、高內聚,是 Laravel 多主題架構的最佳實踐。