Skip to main content

與 Laravel 10 以前的比較

Laravel 11 以「Slim Application Skeleton」為名,大幅刷新了應用程式結構。最大的變化是消除設定的分散,集中至 bootstrap/app.php 一處。
此變更針對新專案。既有的 Laravel 10 應用程式升級後,舊有結構仍可原樣運作。

新的目錄與檔案結構

Skeleton 的目錄結構

bootstrap/app.php — 應用程式設定的中心

僅需這一個檔案,即可設定路由、中介層與例外處理。Laravel 10 以前分散在 app/Http/Kernel.phpapp/Console/Kernel.phpapp/Exceptions/Handler.php 三個檔案的設定,現在都集中在此。

bootstrap/providers.php — 服務提供者清單

此檔案為服務提供者的註冊位置。在 Laravel 10 中原本寫在 config/app.phpproviders 陣列,現已分離至 bootstrap/providers.php。Laravel 11 的預設僅有 AppServiceProvider
composer require 安裝套件時,該套件可能會自動更新 bootstrap/providers.php。並不是 config/app.php 已不再被參考,而是新的註冊建議寫在 bootstrap/providers.php

routes/ 目錄的變更

預設不存在 api.phpchannels.php。可依需求以 Artisan 指令產生。
routes/console.php 中也可以定義排程。

已廢除的檔案

HTTP Kernel 已整合至框架內部的 Illuminate\Foundation\Http\Kernel。中介層的自訂改在 bootstrap/app.phpwithMiddleware() 中進行。
Console Kernel 的兩項職責已被分離。Artisan 指令置於 app/Console/Commands/ 會被自動偵測,排程則寫在 routes/console.php
例外處理器已整合至框架內部的 Illuminate\Foundation\Exceptions\Handler。自訂改在 bootstrap/app.phpwithExceptions() 中進行。

Application::configure() 的運作機制

框架內部的實作

Application::configure()Illuminate\Foundation\Application 的靜態方法。
該方法會執行下列處理:
  1. basePath 決定應用程式的根目錄
  2. 建立 Application 實例
  3. ApplicationBuilder 包裝,套用預設設定
  4. 回傳 ApplicationBuilder 實例
要注意的是,在 configure()已呼叫了 withKernels() / withEvents() / withCommands() / withProviders()。在 bootstrap/app.php 中無需再次呼叫。

以方法鏈進行設定的流程

呼叫 create() 後從 ApplicationBuilder 取出 Application 實例,而 bootstrap/app.phpreturn 的即是此 Application 實例。

從請求到應用程式啟動的流程

public/index.php 為進入點,載入 bootstrap/app.php 以取得 Application。之後 HTTP Kernel 將請求通過中介層的 Pipeline,Router 再派送至 Controller。

ApplicationBuilder 主要方法深入探討

withRouting() — 路由註冊的內部處理

內部會將 callback 註冊至 AppRouteServiceProvider::loadRoutesUsing(),並在應用程式 booting 時註冊 AppRouteServiceProvider
重點:
  • api 路由會自動套用 api 中介層群組及 /api 前綴
  • 若傳入字串至 health,會自動註冊健康檢查端點(預設 /up
  • health 的路徑在維護模式下也會被排除(透過 PreventRequestsDuringMaintenance::except() 設定)
  • 請注意 api 會比 web 先註冊。若同一路徑同時定義 Web 與 API 路由,會以 API 路由優先
  • 若傳入字串至 pages,則會啟用 Laravel Folio 的路由

withMiddleware() — 中介層自訂

withMiddleware() 是在 HttpKernel 被解析之後執行 callback。這是因為使用了 afterResolving() hook。傳入 callback 的 Middleware 物件擁有豐富的自訂方法。

withExceptions() — 例外處理設定

withExceptions() 會先將框架的 Handler 類別註冊為 singleton,再以 afterResolving() 設定 callback。傳給 callback 的是 Exceptions wrapper 物件。

withProviders() — 服務提供者註冊

因為 withProviders()Application::configure() 內已預設呼叫,bootstrap/providers.php 會自動被載入。若要加入額外的提供者,需在 bootstrap/app.php 中明確呼叫。
若傳入 withBootstrapProviders: falsebootstrap/providers.php 將不會被載入。若無特殊理由請予以省略。

其他主要方法

設計意圖:為什麼如此設計

「Code First」的設定

Laravel 10 以前的 app/Http/Kernel.php 採以陣列列舉中介層的方式。這種寫法接近設定檔,缺點是不易獲得 PHP 型別系統及 IDE 的支援。 Laravel 11 改為 withMiddleware(function (Middleware $middleware) { ... }) 的 callback 風格。如此便可享有型別補完,也能自然地寫出使用條件分支或迴圈等邏輯的動態設定。

從「慣例優於設定」到「明確的設定」

api.php 之所以改為選用,是為了解決即便應用程式未使用 API 路由,api 中介層群組仍會一直被載入的問題。方針是:預設不存在不使用的功能。

afterResolving() hook 的活用

withMiddleware()withExceptions() 中使用 afterResolving(),是為了避免設定順序上的問題。ApplicationBuilder 的方法會在應用程式完全啟動前呼叫,實際的處理(對 Kernel 套用設定)則在 Kernel 首次被解析時延遲執行。

自訂範例

讓 API 與 Web 並存

中介層的自訂

將排程集中至 bootstrap/app.php

排程亦可寫在 routes/console.php,但使用 withSchedule() 可將其集中於 bootstrap/app.php

例外處理的自訂

bootstrap/app.php 管理 Container 綁定

若為小型應用程式,也可將簡單的綁定寫在 bootstrap/app.php 而非 AppServiceProvider

Laravel 啟動流程的順序

Laravel 應用程式啟動時,服務提供者與 Application 的 hook 按下列順序執行。
  1. 執行所有 ServiceProvider 的 register()
  2. Application 的 registered()
  3. Application 的 booting()
  4. 執行所有 ServiceProvider 的 boot()
  5. Application 的 booted()
AppServiceProvider 加入下列程式碼即可確認執行順序。
ApplicationBuilderregistered()booting()booted() 只是向 Application 註冊 callback 的方法。通常不需使用,但可用於例如在 booted() 中對啟動準備完成的 Kernel 進行變更等特殊操作。

下一步

服務容器

了解 ApplicationBuilder 內部所使用的服務容器機制。

新應用結構 FAQ

彙整新應用程式結構的常見疑問與解答。
最後修改於 2026年8月2日