跳到主要內容

升級指南

📝 此頁面為 Laravel 官方文檔的繁體中文翻譯。查看原始英文版本

升級指南

高影響變更

中影響變更

低影響變更

從 12.x 升級到 13.0

預計升級時間:10 分鐘

[!NOTE] 我們嘗試記錄每一個可能的破壞性變更。由於其中一些破壞性變更位於框架的偏僻部分,只有一部分變更可能實際影響您的應用程式。為了節省時間,您可以使用 Shift。Shift 是一個社群維護的服務,可以自動化 Laravel 升級。

使用 AI 升級

您可以使用 Laravel Boost 自動化您的升級。Boost 是一個一方 MCP 伺服器,為您的 AI 助手提供引導式升級提示——安裝在任何 Laravel 12 應用程式後,在 Claude Code、Cursor、OpenCode、Gemini 或 VS Code 中使用 /upgrade-laravel-v13 斜線命令開始升級到 Laravel 13。此命令需要 Laravel Boost ^2.0

更新依賴項

影響可能性:高

您應該更新應用程式 composer.json 檔案中的以下依賴項:

  • laravel/framework^13.0
  • laravel/boost^2.0
  • laravel/tinker^3.0
  • phpunit/phpunit^12.0
  • pestphp/pest^4.0

更新 Laravel 安裝器

如果您正在使用 Laravel 安裝器 CLI 工具建立新的 Laravel 應用程式,您應該更新安裝器以確保與 Laravel 13.x 相容。

如果您透過 composer global require 安裝了 Laravel 安裝器,可以使用 composer global update 更新安裝器:

composer global update laravel/installer

或者,如果您正在使用 Laravel Herd 捆綁的 Laravel 安裝器副本,您應該將 Herd 安裝更新到最新版本。

快取

快取前綴和 Session Cookie 名稱

影響可能性:低

Laravel 的預設快取和 Redis 金鑰前綴現在使用連字號分隔的後綴。

在大多數應用程式中,此變更不會適用,因為應用程式級別的配置檔案已經定義了這些值。這主要影響在相應的應用程式配置值不存在時依賴框架級別回退配置的應用程式。

如果您的應用程式依賴這些生成的預設值,升級後快取金鑰和 Session Cookie 名稱可能會更改:

// Laravel <= 12.x
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_cache_';
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_database_';
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_session';

// Laravel >= 13.x
Str::slug((string) env('APP_NAME', 'laravel')).'-cache-';
Str::slug((string) env('APP_NAME', 'laravel')).'-database-';
Str::slug((string) env('APP_NAME', 'laravel')).'-session';

要保留先前的行為,請在環境中明確配置 CACHE_PREFIXREDIS_PREFIXSESSION_COOKIE

StoreRepository 合約:touch

影響可能性:極低

快取合約現在包含一個 touch 方法,用於延長項目 TTL。如果您維護自訂快取儲存實現,您應該添加此方法:

// Illuminate\Contracts\Cache\Store
public function touch($key, $seconds);

快取 serializable_classes 配置

影響可能性:中

預設應用程式 cache 配置現在包含一個 serializable_classes 選項,設置為 false。這強化了快取反序列化行為,以在您的應用程式 APP_KEY 洩露時幫助防止 PHP 反序列化裝載鏈攻擊。如果您的應用程式有意將 PHP 物件儲存在快取中,您應該明確列出可能被反序列化的類別:

'serializable_classes' => [
    App\Data\CachedDashboardStats::class,
    App\Support\CachedPricingSnapshot::class,
],

如果您的應用程式先前依賴反序列化任意快取物件,您需要將該用法遷移到明確的類別允許清單或非物件快取負載(例如陣列)。

容器

Container::call 和可空類別預設值

影響可能性:低

Container::call 現在在不存在綁定時尊重可空類別參數預設值,與 Laravel 12 中引入的構造函數注入行為匹配:

$container->call(function (?Carbon $date = null) {
    return $date;
});

// Laravel <= 12.x: Carbon 實例
// Laravel >= 13.x: null

如果您的方法呼叫注入邏輯依賴先前的行為,您可能需要更新它。

合約

Dispatcher 合約:dispatchAfterResponse

影響可能性:極低

Illuminate\Contracts\Bus\Dispatcher 合約現在包含 dispatchAfterResponse($command, $handler = null) 方法。

如果您維護自訂調度器實現,請將此方法添加到您的類別中。

ResponseFactory 合約:eventStream

影響可能性:極低

Illuminate\Contracts\Routing\ResponseFactory 合約現在包含 eventStream 簽名。

如果您維護此合約的自訂實現,您應該添加此方法。

MustVerifyEmail 合約:markEmailAsUnverified

影響可能性:極低

Illuminate\Contracts\Auth\MustVerifyEmail 合約現在包含 markEmailAsUnverified()

如果您提供此合約的自訂實現,請添加此方法以保持相容性。

資料庫

資料庫 upsert 與 MySQL 或 MariaDB

影響可能性:中

Laravel 現在驗證呼叫者是否為 uniqueBy 提供非空值,並將拋出 InvalidArgumentException 而不是生成無效的 SQL。

儘管 MariaDB 和 MySQL 資料庫驅動程式會忽略 uniqueBy 值並始終使用表的主鍵和唯一索引來偵測現有記錄,但驗證仍然適用。如果 uniqueBy 為空,將拋出 InvalidArgumentException

MySQL DELETE 查詢與 JOINORDER BYLIMIT

影響可能性:低

Laravel 現在為 MySQL 語法編譯完整的 DELETE ... JOIN 查詢,包括 ORDER BYLIMIT

在先前版本中,ORDER BY / LIMIT 子句在連接刪除時可能會被靜默忽略。在 Laravel 13 中,這些子句包含在生成的 SQL 中。因此,不支援此語法的資料庫引擎(例如標準 MySQL / MariaDB 變體)現在可能會拋出 QueryException 而不是執行無界刪除。

Eloquent

模型啟動和巢狀實例化

影響可能性:極低

在模型仍在啟動時建立新的模型實例現在被禁止,並會拋出 LogicException

這影響從模型 boot 方法或 trait boot* 方法內部實例化模型的程式碼:

protected static function boot()
{
    parent::boot();

    // 在啟動期間不再允許...
    (new static())->getTable();
}

將此邏輯移到啟動週期之外以避免巢狀啟動。

多型樞紐表名稱生成

影響可能性:低

當使用自訂樞紐模型類別為多型樞紐模型推斷表名時,Laravel 現在生成複數名稱。

如果您的應用程式依賴先前用於多型樞紐表的單數推斷名稱並使用了自訂樞紐類別,您應該在樞紐模型上明確定義表名。

集合模型序列化還原預先載入的關聯

影響可能性:低

當 Eloquent 模型集合被序列化和還原時(例如在佇列任務中),現在會為集合的模型還原預先載入的關聯。

如果您的程式碼依賴反序列化後關聯不存在,您可能需要調整該邏輯。

HTTP 客戶端

HTTP 客戶端 Response::throwthrowIf 簽名

影響可能性:極低

HTTP 客戶端回應方法現在在方法簽名中聲明其回呼參數:

public function throw($callback = null);
public function throwIf($condition, $callback = null);

如果您在自訂回應類別中覆蓋這些方法,請確保您的方法簽名相容。

通知

預設密碼重設主旨

影響可能性:極低

Laravel 的預設密碼重設郵件主旨已更改:

// Laravel <= 12.x
Reset Password Notification

// Laravel >= 13.x
Reset your password

如果您的測試、斷言或翻譯覆蓋依賴先前的預設字串,請相應地更新它們。

佇列通知和缺失模型

影響可能性:極低

佇列通知現在尊重通知類別上定義的 #[DeleteWhenMissingModels] 屬性和 $deleteWhenMissingModels 屬性。

在先前版本中,缺失模型仍可能導致佇列通知任務失敗,尤其是在您期望它們被刪除的情況下。

佇列

JobAttempted 事件異常負載

影響可能性:低

Illuminate\Queue\Events\JobAttempted 事件現在透過 $exception 暴露異常物件(或 null),取代了先前的布林值 $exceptionOccurred 屬性:

// Laravel <= 12.x
$event->exceptionOccurred;

// Laravel >= 13.x
$event->exception;

如果您監聽此事件,請相應地更新您的監聽器程式碼。

QueueBusy 事件屬性重新命名

影響可能性:低

Illuminate\Queue\Events\QueueBusy 事件屬性 $connection 已重新命名為 $connectionName,以與其他佇列事件保持一致。

如果您的監聽器引用 $connection,請將其更新為 $connectionName

Queue 合約方法添加

影響可能性:極低

Illuminate\Contracts\Queue\Queue 合約現在包含先前僅在文件區塊中聲明的佇列大小檢查方法。

如果您維護此合約的自訂佇列驅動程式實現,請添加以下方法的實現:

  • pendingSize
  • delayedSize
  • reservedSize
  • creationTimeOfOldestPendingJob

路由

網域路由註冊優先順序

影響可能性:低

具有明確網域的路由現在在路由匹配中優先於非網域路由。

這允許萬用子網域路由即使在非網域路由較早註冊時也能保持一致的行為。如果您的應用程式依賴網域和非網域路由之間的先前註冊優先順序,請檢查路由匹配行為。

排程

withScheduling 註冊時機

影響可能性:極低

透過 ApplicationBuilder::withScheduling() 註冊的排程現在會延遲到 Schedule 被解析時。

如果您的應用程式依賴引導期間的即時排程註冊時機,您可能需要調整該邏輯。

安全性

請求偽造保護

影響可能性:高

Laravel 的 CSRF 中介層已從 VerifyCsrfToken 重新命名為 PreventRequestForgery,現在包含使用 Sec-Fetch-Site 標頭的請求來源驗證。

VerifyCsrfTokenValidateCsrfToken 仍作為已棄用的別名存在,但直接引用應更新為 PreventRequestForgery,特別是在測試或路由定義中排除中介層時:

use Illuminate\Foundation\Http\Middleware\PreventRequestForgery;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;

// Laravel <= 12.x
->withoutMiddleware([VerifyCsrfToken::class]);

// Laravel >= 13.x
->withoutMiddleware([PreventRequestForgery::class]);

中介層配置 API 現在還提供 preventRequestForgery(...)

支援

Manager extend 回呼綁定

影響可能性:低

透過 manager extend 方法註冊的自訂驅動程式閉包現在綁定到 manager 實例。

如果您先前依賴其他綁定物件(例如服務提供者實例)作為這些回呼中的 $this,您應該使用 use (...) 將這些值移入閉包捕獲中。

Str 工廠在測試之間重置

影響可能性:低

Laravel 現在在測試拆卸期間重置自訂 Str 工廠。

如果您的測試依賴自訂 UUID / ULID / 隨機字串工廠在測試方法之間持續存在,您應該在每個相關測試或設定鉤子中設定它們。

Js::from 預設使用未轉義的 Unicode

影響可能性:極低

Illuminate\Support\Js::from 現在預設使用 JSON_UNESCAPED_UNICODE

如果您的測試或前端輸出比較依賴轉義的 Unicode 序列(例如 \u00e8),請更新您的預期。

實用工具

Symfony PHP 8.5 Polyfill 和全域函數衝突

影響可能性:低

Laravel 13 引入了對 symfony/polyfill-php85 的依賴。在低於 8.5 的 PHP 版本上,除非在引導期間已定義,否則此 polyfill 會定義全域函數,如 array_first()array_last()

這些函數可能與使用相同名稱的舊版輔助函式套件(如 laravel/helpers)或自訂全域輔助函數衝突。例如,歷史上的 array_first() 輔助函數接受一個回呼來返回第一個匹配的元素,而 polyfill 版本只返回陣列的第一個元素。

為了避免衝突並確保跨 PHP 版本的一致行為,您應該優先使用 Illuminate\Support\Arr 方法:

use Illuminate\Support\Arr;

Arr::first($array, function ($value) {
  return /* condition */;
});

視圖

分頁 Bootstrap 視圖名稱

影響可能性:低

Bootstrap 3 預設的內部分頁視圖名稱現在是明確的:

// Laravel <= 12.x
pagination::default
pagination::simple-default

// Laravel >= 13.x
pagination::bootstrap-3
pagination::simple-bootstrap-3

如果您的應用程式直接引用舊的分頁視圖名稱,請更新這些引用。

其他

我們還鼓勵您查看 laravel/laravel GitHub 儲存庫中的變更。雖然其中許多變更不是必需的,但您可能希望使這些檔案與您的應用程式保持同步。其中一些變更將在本升級指南中介紹,但其他變更(例如配置檔案或註解的變更)則不會。您可以使用 GitHub 比較工具輕鬆查看變更,並選擇對您重要的更新。