--- tags: laravel --- # 視圖View ![](https://i.imgur.com/rogIoHn.jpg) ## 簡介 很顯然的,直接回傳以字串的形式回傳整份 HTML 文件是不現實的。幸好視圖提供了一種便利的方式讓我們把整份 HTML 文件切分成多個檔案。視圖把控制器與商業邏輯抽離出去後存放在 resources/views 資料夾內,一個簡單的視圖檔長得像這樣: ``` //resources\views\greeting.blade.php <html> <body> <h1>Hello, {{ $name }}</h1> </body> </html> ``` 假如有一個檔案是 resources/views/greeting.blade.php ,我們能夠使用全域幫助函式 view() 來回傳這個檔案 ``` //routes\web.php Route::get('/', function () { return view('greeting', ['name' => 'James']); }); ``` 如果你對於如何使用 Blade 模板來開發視圖感到興趣的話,歡迎參考[視圖的Blade引擎](/Q4THMvbaSnCDfpAqUMLv6w) ## 建立並渲染視圖 你能夠透過將副檔名為 .blade.php 的檔案放在專案的 resources/views 資料夾。 .blade.php副檔名能讓框架知道該檔案包含 Blade 版型。 Blade 版型包含 HTML 以及 Blade 標籤,而 Blade 標籤能讓你輕鬆輸出參數,建立條件判斷式 . 遞迴 以及更多 一旦你有建立一個視圖,你就能在路由或控制器使用全域 view() 來回傳視圖 ``` Route::get('/', function () { return view('greeting', ['name' => 'James']); }); ``` 視圖也可透過 View Facade 來回傳 ``` use Illuminate\Support\Facades\View; return View::make('greeting', ['name' => 'James']); ``` view() 幫助函式的第一參數為放在 resources/views 資料夾的視圖名稱,第二參數是參數陣列用以提供視圖所需要的資料。比如上面這個例子,將傳入一個名為name的參數,值為James ### 子視圖目錄 視圖也可以放在 resources/views 的子資料夾內,只需要透過點語法來標註它的位置。例如,假如有一個視圖檔是 resources/views/admin/profile.blade.php ,你能夠在路由或控制器使用這個語法來回傳 `return view('admin.profile', $data);` > 注意 > > 視圖資料夾名稱不能夠包含.這個字元 ### 建立第一個可用視圖 使用 first() ,你可以創建傳入視圖陣列中第一個存在的視圖。 如果你的應用或開發的第三方套件允許自定義或複寫視圖,這非常有用 ``` use Illuminate\Support\Facades\View; return View::first(['custom.admin', 'admin'], $data); ``` ### 判斷視圖是否存在 如果需要判斷視圖檔案是否存在,可以使用 View Facade的 exists()。如果該視圖存在的話,exists() 會返回 true ``` use Illuminate\Support\Facades\View; if (View::exists('emails.customer')) { // } ``` ## 傳資料到視圖 正如前面範例中所見,可以將一組陣列傳遞給視圖 `return view('greetings', ['name' => 'Victoria']);` 以這種方式傳遞資料時,資料應該是具有鍵值對的陣列。在視圖中可以使用相應的鍵訪問每個值,例如 <?php echo $key; ?>。作為將完整的資料陣列傳遞給 view 幫助函式的替代方法,您可以使用 with() 將各個參數添加到視圖中: 作為一個替代傳遞完整的資料陣列到 view() 的方法,你能夠使用 with() 來傳入個別參數。 這個 with() 回傳一個視圖物件,所以你可以繼續接著呼叫更多的 with() 來傳入更多的參數 ``` return view('greeting') ->with('name', 'Victoria') ->with('occupation', 'Astronaut'); ``` ### 分享資料到所有視圖 有時候,你可能需要共享參數給應用的所有視圖。 你可以在服務提供器的 boot() 中呼叫 View Facade 的 share() 。例如可以將它們添加到 AppServiceProvider 或者為它們生成一個單獨的服務提供器: ``` <?php namespace App\Providers; use Illuminate\Support\Facades\View; class AppServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ public function register() { // } /** * Bootstrap any application services. * * @return void */ public function boot() { View::share('key', 'value'); } } ``` ## 視圖合成器 視圖合成器是在呈現視圖時呼叫的回呼或類別方法。如果希望每次呈現視圖時將該視圖需要的資料自動綁定進去,則視圖合成器可以幫助你將這些邏輯組織到一起,尤其是該視圖需要在多個路由或控制器中重複回傳且用到相同資料時特別實用 一般來說,視圖合成器將會在你應用的服務供應器內註冊。比如你可以在 App\Providers\ViewServiceProvider 來存放這些邏輯 我們將使用 View Facade 的 composer() 來註冊視圖合成器。 Laravel 預設並不包含用於存放視圖合成器的資料夾但你可以自己建立並且組織它。比如你可以建立一個 app/Http/View/Composers 資料夾來存放所有的視圖合成器類別 ``` //App\Providers\ViewServiceProvider.php <?php namespace App\Providers; use App\Http\View\Composers\ProfileComposer; use Illuminate\Support\Facades\View; use Illuminate\Support\ServiceProvider; class ViewServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ public function register() { // } /** * Bootstrap any application services. * * @return void */ public function boot() { // Using class based composers... View::composer('profile', ProfileComposer::class); // Using closure based composers... View::composer('dashboard', function ($view) { // }); } } ``` > 注意: > > 如果你創建了新的一個服務供應器來存放你註冊視圖合成器的程式碼,你需將這個服務供應器添加到設定文件 config/app.php 的 providers 陣列中 現在我們註冊了視圖合成器,每次渲染 profile 視圖時都會執行 ProfileComposer 類別的 compose() 。接著來定義視圖合成器類別 ``` //App\Http\View\Composers\ProfileComposer.php <?php namespace App\Http\View\Composers; use App\Repositories\UserRepository; use Illuminate\View\View; class ProfileComposer { /** * The user repository implementation. * * @var \App\Repositories\UserRepository */ protected $users; /** * Create a new profile composer. * * @param \App\Repositories\UserRepository $users * @return void */ public function __construct(UserRepository $users) { // Dependencies automatically resolved by service container... $this->users = $users; } /** * Bind data to the view. * * @param \Illuminate\View\View $view * @return void */ public function compose(View $view) { $view->with('count', $this->users->count()); } } ``` 視圖合成器的 compose() 會在視圖渲染之前被呼叫,並傳入一個 Illuminate\View\View 實例。你可以使用 with() 將資料傳進視圖 >技巧: > >所有的視圖合成器都會通過服務容器來進行解析,所以你可以在視圖合成器的建構子中透過型別提示需要注入的依賴項 ### 將一個視圖合成器綁定到多個視圖 通過將一組視圖陣列而非字串來作為第一個參數傳入 composer() ,可以一次綁定多個視圖到視圖合成器中: ``` //App\Providers\ViewServiceProvider.php use App\Http\Views\Composers\MultiComposer; View::composer( ['profile', 'dashboard'], MultiComposer::class ); ``` 另外 composer() 的第一個參數也接受 * 字元(wildcard代表任何字串),這允許你將視圖合成器綁定到所有視圖 ``` //App\Providers\ViewServiceProvider.php View::composer('*', function ($view) { // }); ``` ### 視圖構造器 視圖構造器(creators)和視圖合成器非常相似。唯一不同之處在於視圖構造器在視圖實例化之後執行,而視圖合成器在視圖即將渲染時執行。使用 creator() 註冊視圖構造器: ``` //App\Providers\ViewServiceProvider.php use App\Http\View\Creators\ProfileCreator; use Illuminate\Support\Facades\View; View::creator('profile', ProfileCreator::class); ``` ## 視圖優化 正常情況下視圖是需要時才進行編譯的。當執行渲染視圖的請求時,Laravel 將確認該視圖是否有編譯好的檔案。如果已編譯視圖有存在,Laravel 還會比較未編譯視圖是否在編譯後又做了修改。如果已編譯視圖不存在,又或者視圖編譯後又被修改,Laravel 都將編譯該視圖 而在請求期間去編譯視圖是會對性能產生影響的,因此 Laravel 提供了 view:cache 的 Artisan 命令來進行預編譯應用中的所有視圖檔案。為提高性能,你可能希望在部署過程中執行以下命令: `php artisan view:cache` 你也可以使用 view:clear 命令來清除視圖的快取 `php artisan view:clear`