Skip to main content

前言

Laravel 9 於 2022 年 2 月 8 日發佈。本指南整理從 Laravel 8.x 升級到 9.x 的步驟與影響較大的變更點。
升級預估所需時間約為 30 分鐘。不過因為郵件寄送、檔案儲存、自訂 cast、以及框架核心類別的覆寫狀況,工作量可能會增加。

使用 Laravel Shift 自動化升級

也可以使用 Laravel Shift 自動化升級。Shift 會協助更新 composer.json 與設定檔,作為差異確認的起點很方便。

依影響程度分類的變更

影響程度:高

  • 更新依賴套件
  • 遷移到 Flysystem 3.x
  • 遷移到 Symfony Mailer

影響程度:中

  • BelongsToManyfirstOrNew / firstOrCreate / updateOrCreate 方法
  • Custom Cast 與 null 的行為
  • HTTP client 的預設 timeout
  • PHP Return Types 的新增
  • Postgres 的 schema 設定名稱變更
  • 廢除 assertDeleted 方法
  • lang 目錄的搬移
  • 密碼規則的變更
  • when / unless 方法的變更
  • validation 中未驗證陣列 key 的處理

升級步驟

更新依賴套件

影響程度:高 Laravel 9 需要 PHP 8.0.2 以上。首先請重新檢視 composer.json 的依賴。
另外,對應的應用程式需要以下更新。
  • 移除 facade/ignition,改用 spatie/laravel-ignition:^1.0
  • 若使用 pusher/pusher-php-server,請更新到 ^5.0
  • 確認使用中的第三方套件是否有 Laravel 9 相容版本
  • 若使用 Vonage 通知 channel,也請確認個別的升級指南
更新後執行以下指令安裝依賴。

PHP 版本需求

影響程度:高 Laravel 9 必須使用 PHP 8.0.2 以上。請在 CI、本機開發環境、正式環境的 PHP 版本都對齊後再進行升級。

遷移到 Symfony Mailer

影響程度:高 Laravel 9 的一大變更之一是從 2021 年 12 月結束維護的 SwiftMailer 遷移到 Symfony Mailer。僅使用一般 Mail::to()->send() 的應用影響較小,但若直接使用 SwiftMailer 的低階 API,就需要確認。

Driver 依賴套件

withSwiftMessagewithSymfonyMessage

Illuminate\Mail\Mailersendhtmlrawplain 現在會回傳 Illuminate\Mail\SentMessage 而不是 void。另外 MessageSent 事件的 message 屬性中,現在會是 Symfony\Component\Mime\Email 而非 Swift_Message

重新檢視 SMTP 設定

Symfony Mailer 中 SMTP 的 stream 選項已廢除,支援的設定移到最上層。
auth_mode 也不再需要明確設定。將營運方式改為在送出前驗證電子郵件地址,會比事後回收無效地址更安全。

遷移到 Flysystem 3.x

影響程度:高 Laravel 9 將 Storage facade 的內部實作從 Flysystem 1.x 更新到 3.x。檔案操作方法盡可能保持相容,但在例外、回傳值、adapter 註冊等部分有差異。

追加安裝 Driver

Storage 主要行為變更

  • put / write / writeStream 預設會覆寫既有檔案
  • 寫入失敗時回傳 false 而非例外
  • 讀取不存在的檔案時回傳 null 而非例外
  • 刪除不存在的檔案時 delete 回傳 true
  • cached adapter 已被移除,可移除 disk 設定中的 cache key
若想像過去一樣在寫入失敗時使用例外,請設定 throw 選項。
若有註冊自訂 filesystem driver,請調整 Storage::extend() 的 callback 直接回傳 Illuminate\Filesystem\FilesystemAdapter

BelongsToManyfirstOrNew / firstOrCreate / updateOrCreate

影響程度:中 Laravel 8 中傳給這些方法的第 1 個引數屬性陣列是與中間表比對。Laravel 9 則是與關聯 model 的資料表比對。
另外 firstOrCreate 開始可接收第 2 引數 $values,行為與其他 relation 對齊。

Custom Cast 與 null

影響程度:中 Laravel 9 中,即使對 cast 對象指派 null,也會呼叫 custom cast 的 set 方法。未預期收到 null 的 cast,升級後可能會拋出例外。

HTTP client 的預設 timeout

影響程度:中 HTTP client 的預設 timeout 改為 30 秒。以前可能會無限等待。

PHP Return Types 的新增

影響程度:中 Laravel 9 中,為配合 PHP 本體或 Symfony 的需求,各種核心類別已加上回傳型別。若你繼承 Laravel 的核心類別並覆寫 offsetGetoffsetSetjsonSerializeopenread 等方法,也請在自己的實作加上相同的回傳型別。

Postgres 的 schema 設定名稱變更

影響程度:中 若在 Postgres 連線設定 search path,請將 config/database.php 的 key 名稱從 schema 改為 search_path

assertDeletedassertModelMissing

影響程度:中 用於確認 model 刪除的 assertDeleted 請替換為 assertModelMissing

lang 目錄的搬移

影響程度:中 新的 Laravel 9 應用中,語言檔案的放置位置從 resources/lang 改為專案根目錄的 lang。若只是直接執行既有應用影響不大,但若要對齊新的 skeleton,或套件公開翻譯檔案時請重新檢視。

密碼規則的變更

影響程度:中 驗證目前登入使用者的密碼是否相符的 password rule 已重新命名為 current_password

when / unless 方法的變更

影響程度:中 Laravel 8 中將 closure 傳給 whenunless 時,該 closure 本身會被評估為 truthy,可能導致意外的條件分支執行。Laravel 9 中會執行 closure,並將其回傳值作為條件使用。

未驗證陣列 key 的處理

影響程度:中 Laravel 9 中,validated() 回傳的陣列總是會排除未驗證的陣列 key。若要維持 Laravel 8 的相容行為,只在必要時明確呼叫 includeUnvalidatedArrayKeys()

總結

從 Laravel 8 升級到 9,主要是更新 PHP 到 8.0.2、遷移到 Symfony Mailer、對應 Flysystem 3.x。先檢查郵件寄送、儲存、自訂 cast、測試 helper,可以減少升級後的問題。

參考資料

最後修改於 2026年8月2日