版本資訊

版本策略

Laravel 及其第一方套件都遵守 語義化版本。框架的主要更新會每年釋出 (約在二月時),而次版本與修訂版則可能頻繁到每週更新。次版本與修訂版 絕對不會 包含中斷性變更(Breaking Change)

由於 Laravel 的主要更新會包含中斷性變更,因此在應用程式或套件中參照 Laravel 框架或其組件時,應使用如 ^9.0 這樣的版本限制式。然而,我們竭力確保主要更新應可於一天之內完成。

帶名稱的引數

帶名稱引數功能尚未包含在 Laravel 的向下相容性方針內。我們可能會在有必要的時候更改函式的參數名稱以改進 Laravel 的程式碼。因此,在使用帶名稱引數呼叫 Laravel 方法時應格外注意,並瞭解到引數名稱未來可能會有所更改。

支援政策

所有的 Laravel 版本都提供 18 個月的 Bug 修正,以及 2 年的安全性修正。對於其他的函式庫,如 Lumen,則只有最新的主要版本會收到 Bug 修正。此外,也請參考 Laravel 支援的資料庫版本。

版本PHP (*)釋出日期Bug 修正期限安全性修正期限
6 (LTS)7.2 - 8.02019 年 9 月 3 日2022 年 1 月 25 日2022 年 9 月 6 日
77.2 - 8.02020 年 3 月 3 日2020 年 10 月 6 日2021 年 3 月 3 日
87.3 - 8.12020 年 9 月 8 日2022 年 7 月 26 日2023 年 1 月 24 日
98.0 - 8.22022 年 2 月 8 日2023 年 8 月 8 日2024 年 2 月 6 日
108.1 - 8.22023 年第 1 季2024 年 8 月 6 日2025 年 2 月 4 日
End of life
Security fixes only

(*) 支援的 PHP 版本

Laravel 9

讀者可能已經知道,從 Laravel 8 開始,Laravel 改為每年釋出新的主要版本。在此之前,每 6 個月都會釋出主要版本。這個改變是為了降低社群維護的負擔,並讓我們的開發團隊能想辦法在不包含中斷性更改 (Breaking Change) 的情況下繼續提供驚艷且強大的新功能。因此,我們在 Laravel 8 中,以不破壞向下相容性的前提下推出了許多強健的功能,如平行測試 (Parallel Testing) 支援、改進了 Breeze 入門套件、HTTP 用戶端的改進、甚至還出了一些如「一對多種之一 (Has One of Many)」等新的 Eloquent 關聯類型。

因此,我們對於在目前版本中釋出新功能的承諾也將導致未來的「主要 (Major)」版本將著重於一些「維護性」的任務,如更新上游套件等,讀者稍後可以在本版本資訊內讀到。

Laravel 9 延續了 Laravel 8.x 中推出的各種改進,並支援 Symfony 6.0 元件、Symfony Mailer、Flysystem 3.0、改進過的 route:list 輸出、Laravel Scout 資料庫 Driver、新的 Eloquent 存取子 / 更動子語法、通過 Enum 進行的隱式路由繫結、以及其他多個 Bug 修正與可用性提升。

PHP 8.0

Laravel 9.x 所要求的最小 PHP 版本為 8.0。

Symfony Mailer

Symfony Mailer 支援由 Dries Vints, James Brooks, 與 Julius Kiekbusch 參與貢獻

在以前版本的 Laravel 中,我們使用 Swift Mailer 函式庫來寄送外部 E-Mail。不過,這個函式庫已不在維護,Symfony Mailer 為其後繼者。

請參考升級指南來瞭解如何確保你的專案能相容於 Symfony Mailer。

Flysystem 3.x

Flysystem 3.x 支援由 Dries Vints 參與貢獻

Laravel 9.x 更新了上游的 Flysystem 相依性套件為 Flysystem 3.x。Flysystem 驅動了 Storage Facade 中提供的所有檔案系統互動功能。

請參考升級指南來瞭解如何確保你的專案能相容於 Flysystem 3.x。

改進過的 Eloquent 存取子與更動子

改進過的 Eloquent Accessor(存取子)Mutator(更動子)Taylor Otwell 參與貢獻

Laravel 9.x 提供了一種定義 Eloquent 存取子與更動子的全新方法。在之前版本的 Laravel 中,唯一一種定義存取子與更動子的方法就只有在 Model 中像這樣定義由前置詞的方法:

1public function getNameAttribute($value)
2{
3 return strtoupper($value);
4}
5 
6public function setNameAttribute($value)
7{
8 $this->attributes['name'] = $value;
9}
1public function getNameAttribute($value)
2{
3 return strtoupper($value);
4}
5 
6public function setNameAttribute($value)
7{
8 $this->attributes['name'] = $value;
9}

不過,在 Laravel 9.x 中,只需要標示回傳型別為 Illuminate\Database\Eloquent\Casts\Attribute,就可以使用不含前置詞的單一一個方法來定義存取子與更動子:

1use Illuminate\Database\Eloquent\Casts\Attribute;
2 
3public function name(): Attribute
4{
5 return new Attribute(
6 get: fn ($value) => strtoupper($value),
7 set: fn ($value) => $value,
8 );
9}
1use Illuminate\Database\Eloquent\Casts\Attribute;
2 
3public function name(): Attribute
4{
5 return new Attribute(
6 get: fn ($value) => strtoupper($value),
7 set: fn ($value) => $value,
8 );
9}

此外,這種定義存取子的新方法也會將以屬性回傳的物件值快取起來,就跟自訂型別轉換類別一樣:

1use App\Support\Address;
2use Illuminate\Database\Eloquent\Casts\Attribute;
3 
4public function address(): Attribute
5{
6 return new Attribute(
7 get: fn ($value, $attributes) => new Address(
8 $attributes['address_line_one'],
9 $attributes['address_line_two'],
10 ),
11 set: fn (Address $value) => [
12 'address_line_one' => $value->lineOne,
13 'address_line_two' => $value->lineTwo,
14 ],
15 );
16}
1use App\Support\Address;
2use Illuminate\Database\Eloquent\Casts\Attribute;
3 
4public function address(): Attribute
5{
6 return new Attribute(
7 get: fn ($value, $attributes) => new Address(
8 $attributes['address_line_one'],
9 $attributes['address_line_two'],
10 ),
11 set: fn (Address $value) => [
12 'address_line_one' => $value->lineOne,
13 'address_line_two' => $value->lineTwo,
14 ],
15 );
16}

Enum Eloquent 屬性型別轉換

exclamation

Enum 型別轉換只可在 PHP 8.1 以上使用。

Enum 型別轉換由 Mohamed Said 參與貢獻

現在,Eloquent 也能讓我們將屬性值轉換為 PHP 的 「Backed」Enum 了。為此,可在 Model 中的 $casts 屬性陣列中指定要型別轉換的屬性與 Enum:

1use App\Enums\ServerStatus;
2 
3/**
4 * The attributes that should be cast.
5 *
6 * @var array
7 */
8protected $casts = [
9 'status' => ServerStatus::class,
10];
1use App\Enums\ServerStatus;
2 
3/**
4 * The attributes that should be cast.
5 *
6 * @var array
7 */
8protected $casts = [
9 'status' => ServerStatus::class,
10];

定義好 Model 的型別轉換後,每次存取該屬性時就會自動轉換對 Enum 進行轉換:

1if ($server->status == ServerStatus::Provisioned) {
2 $server->status = ServerStatus::Ready;
3 
4 $server->save();
5}
1if ($server->status == ServerStatus::Provisioned) {
2 $server->status = ServerStatus::Ready;
3 
4 $server->save();
5}

使用 Enum 的隱式路由繫結

隱式路由繫結由 Nuno Maduro 參與貢獻

PHP 8.1 新增了對 Enum 的支援。Laravel 9.x 中提供了能在路由定義中對 Enum 進行型別提示的功能。加上型別提示後,只有當網址中的路由片段 (Segment) 為有效的 Enum 時,Laravel 才會叫用該路由。若不是有效的 Enum 值,則會自動回傳 HTTP 404 回應。舉例來說,假設有下列 Enum:

1enum Category: string
2{
3 case Fruits = 'fruits';
4 case People = 'people';
5}
1enum Category: string
2{
3 case Fruits = 'fruits';
4 case People = 'people';
5}

我們可以定義一個只有當 {category} 路由片段為 fruitspeople 時才會被叫用的路由。若為其他值,則會回傳 HTTP 404 回應:

1Route::get('/categories/{category}', function (Category $category) {
2 return $category->value;
3});
1Route::get('/categories/{category}', function (Category $category) {
2 return $category->value;
3});

Route 繫結的強制限定範圍

強制限定作用範圍的繫結由 Claudio Dekker 參與貢獻

在之前版本的 Laravel 中,我們可以在路由定義中限定第二個 Eloquent Model 一定要是前一個 Eloquent Model 的子 Model。舉例來說,假設有下列這樣通過 Slug 取得特定使用者的部落格貼文的路由定義:

1use App\Models\Post;
2use App\Models\User;
3 
4Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
5 return $post;
6});
1use App\Models\Post;
2use App\Models\User;
3 
4Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
5 return $post;
6});

在巢狀路由參數中使用自訂索引鍵的隱式繫結時,Laravel 會自動使用慣例來猜測上層 Model 的關聯名稱,並在查詢巢狀 Model 時以此限定查詢範圍。不過,在以前版本的 Laravel 中,只有在子路由繫結上使用自訂索引鍵時才可使用此功能。

不過,在 Laravel 9.x 中,就算沒有提供自訂索引鍵,我們還是可以告訴 Laravel 要如何對「子」繫結限定範圍。為此,我們可以在定義路由時叫用 scopeBindings 方法:

1use App\Models\Post;
2use App\Models\User;
3 
4Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
5 return $post;
6})->scopeBindings();
1use App\Models\Post;
2use App\Models\User;
3 
4Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
5 return $post;
6})->scopeBindings();

或者,也可以讓整個路由定義群組使用限定範圍的繫結:

1Route::scopeBindings()->group(function () {
2 Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
3 return $post;
4 });
5});
1Route::scopeBindings()->group(function () {
2 Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
3 return $post;
4 });
5});

Controller 路由群組

路由群組的改進由 Luke Downing 參與貢獻

我們現在可以使用 controller 方法來在路由群組中為所有的路由定義通用的 Controller 了。定義好之後,當定義路由時,就只需要提供要叫用的 Controller 方法即可:

1use App\Http\Controllers\OrderController;
2 
3Route::controller(OrderController::class)->group(function () {
4 Route::get('/orders/{id}', 'show');
5 Route::post('/orders', 'store');
6});
1use App\Http\Controllers\OrderController;
2 
3Route::controller(OrderController::class)->group(function () {
4 Route::get('/orders/{id}', 'show');
5 Route::post('/orders', 'store');
6});

全文索引與 Where 子句

全文索引與「where」子句由 Taylor OtwellDries Vints 參與貢獻

現在,在使用 MySQL 或 PostgresSQL 時,我們可以在欄位定義中新增 fullText 方法來產生全文索引 (Full Text Indexes):

1$table->text('bio')->fullText();
1$table->text('bio')->fullText();

此外,也可以使用 whereFullTextorWhereFullText 方法來在查詢中為有全文索引的欄位加上全文「where」子句。Laravel 會依據底層的資料庫系統將這些方法轉換為適當的 SQL。舉例來說,使用 MySQL 的專案會產生 MATCH AGAINST 子句:

1$users = DB::table('users')
2 ->whereFullText('bio', 'web developer')
3 ->get();
1$users = DB::table('users')
2 ->whereFullText('bio', 'web developer')
3 ->get();

Laravel Scout 資料庫引擎

Laravel Scout 資料庫引擎由 Taylor OtwellDries Vints 參與貢獻

若你的專案使用中小型的資料庫,或是資料庫的工作量 (Workload) 不高的話,現在,你可以使用 Scout 的「database」引擎,而不需使用如 Algolia 或 MeiliSearch 等專門的搜尋服務。在從現有資料庫過濾結果時,資料庫引擎會使用「where like」查詢語句來取得搜尋結果。

要瞭解更多有關 Scout 資料庫引擎的資訊,請參考 Scout 說明文件

轉譯內嵌的 Blade 樣板

轉譯內嵌的 Blade 樣板由 Jason Beggs 參與貢獻。轉譯內嵌的 Blade 元件由 Toby Zerner 參與貢獻

有時候,我們可能會想將原始的 Blade 樣板字串轉譯為有效的 HTML。我們可以通過 Blade Facade 所提供的 render 方法來達成。render 方法接受 Blade 樣板字串,以及一個用來提供給樣板的可選資料陣列:

1use Illuminate\Support\Facades\Blade;
2 
3return Blade::render('Hello, {{ $name }}', ['name' => 'Julian Bashir']);
1use Illuminate\Support\Facades\Blade;
2 
3return Blade::render('Hello, {{ $name }}', ['name' => 'Julian Bashir']);

類似地,只要將元件實體傳給 renderComponent 方法,就可轉譯給定的類別元件:

1use App\View\Components\HelloComponent;
2 
3return Blade::renderComponent(new HelloComponent('Julian Bashir'));
1use App\View\Components\HelloComponent;
2 
3return Blade::renderComponent(new HelloComponent('Julian Bashir'));

Slot 名稱捷徑

Slot 名稱捷徑由 Caleb Porzio 參與貢獻

在之前版本的 Laravel 中,可在 x-slot 標籤上使用 name 屬性來提供 Slot 名稱:

1<x-alert>
2 <x-slot name="title">
3 Server Error
4 </x-slot>
5 
6 <strong>Whoops!</strong> Something went wrong!
7</x-alert>
1<x-alert>
2 <x-slot name="title">
3 Server Error
4 </x-slot>
5 
6 <strong>Whoops!</strong> Something went wrong!
7</x-alert>

不過,從 Laravel 9.x 開始,就可以使用更方便簡潔的語法來指定 Slot 的名稱:

1<x-slot:title>
2 Server Error
3</x-slot>
1<x-slot:title>
2 Server Error
3</x-slot>

Checked / Selected Blade 指示詞

Checked 與 Selected Blade 指示詞由 Ash AllenTaylor Otwell 參與貢獻

為了方便起見,現在可以使用 @checked 指示詞來輕鬆地標示給定 HTML 勾選框為「已勾選(Checked)」。這個指示詞會在條件為 true 時 Echo checked

1<input type="checkbox"
2 name="active"
3 value="active"
4 @checked(old('active', $user->active)) />
1<input type="checkbox"
2 name="active"
3 value="active"
4 @checked(old('active', $user->active)) />

類似地,@selected 指示詞可用來表示給定 Select 選項應為「已選擇(Selected)」:

1<select name="version">
2 @foreach ($product->versions as $version)
3 <option value="{{ $version }}" @selected(old('version') == $version)>
4 {{ $version }}
5 </option>
6 @endforeach
7</select>
1<select name="version">
2 @foreach ($product->versions as $version)
3 <option value="{{ $version }}" @selected(old('version') == $version)>
4 {{ $version }}
5 </option>
6 @endforeach
7</select>

Bootstrap 5 的分頁 View

Bootstrap 5 分頁 View 由 Jared Lewis 參與貢獻

現在,Laravel 提供了適用於 Bootstrap 5 的分頁 View。若要使用這些 View 來替代預設的 Tailwind View,可以在 App\Providers\AppServiceProvider 內的 boot 方法中呼叫 Paginator 的 useBootstrapFive 方法:

1use Illuminate\Pagination\Paginator;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Paginator::useBootstrapFive();
11}
1use Illuminate\Pagination\Paginator;
2 
3/**
4 * Bootstrap any application services.
5 *
6 * @return void
7 */
8public function boot()
9{
10 Paginator::useBootstrapFive();
11}

對巢狀陣列資料認證的改進

針對巢狀陣列輸入的表單驗證改進由 Steve Bauman 參與貢獻

有時候,在為屬性指派認證規則時,我們可能會想存取給定巢狀陣列項目的值。現在,我們可以使用 Rule::forEach 方法來達成。forEach 方法接受一個閉包。在認證時,每次迭代陣列屬性都會叫用一次這個閉包,且該閉包會收到屬性值與完整展開的屬性名稱。該閉包應回傳一個陣列,其中包含要指派給陣列元素的認證規則:

1use App\Rules\HasPermission;
2use Illuminate\Support\Facades\Validator;
3use Illuminate\Validation\Rule;
4 
5$validator = Validator::make($request->all(), [
6 'companies.*.id' => Rule::forEach(function ($value, $attribute) {
7 return [
8 Rule::exists(Company::class, 'id'),
9 new HasPermission('manage-company', $value),
10 ];
11 }),
12]);
1use App\Rules\HasPermission;
2use Illuminate\Support\Facades\Validator;
3use Illuminate\Validation\Rule;
4 
5$validator = Validator::make($request->all(), [
6 'companies.*.id' => Rule::forEach(function ($value, $attribute) {
7 return [
8 Rule::exists(Company::class, 'id'),
9 new HasPermission('manage-company', $value),
10 ];
11 }),
12]);

Laravel Breeze API 與 Next.js

Laravel Breeze API Scaffolding 與 Next.js 入門套件由 Taylor OtwellMiguel Piedrafita 參與貢獻

Laravel Breeze 入門套件現在有了「API」Scaffolding 模式,且有了完整的 Next.js 前端實作。如果你想使用 Laravel 作為後端並使用 Laravel Sanctum 的登入 API 給 JavaScript 前端使用的話,就適合這個入門套件 Scaffolding。

改進過的 Ignition 例外頁面

Ignition 由 Spatie 開發

Ignition 是由 Spatie 製作的開放原始碼例外偵錯頁面。Ignition 現已被重新設計。Laravel 9.x 隨附了這個全新、改進過的 Ignition,並包含了亮色 / 暗色主題、可自訂的「在編輯器中開啟」功能⋯等。

改進過的 route:list CLI 輸出

改進過的 route:list CLI 輸出由 Nuno Maduro 參與貢獻

Laravel 9.x 更新中的 route:list CLI 已大幅改進,能讓你在探索路由定義時獲得全新、漂亮的體驗。

使用 Artisan test 指令來取得測試覆蓋率

使用 Artisan test 指令來取得測試覆蓋率由 Nuno Maduro 參與貢獻

現在,Artisan test 指令有了全新的 --coverage 選項,能讓你用來確認測試為專案提供了多少的程式碼覆蓋率:

1php artisan test --coverage
1php artisan test --coverage

測試覆蓋率會直接顯示在 CLI 輸出中。

此外,若想指定測試覆蓋率的最小百分比值,可以使用 --min 選項。當沒滿足最小值時,測試套件就會執行失敗:

1php artisan test --coverage --min=80.3
1php artisan test --coverage --min=80.3

Soketi Echo 伺服器

Soketi Echo 伺服器由 Alex Renoki 開發

雖然這個功能不侷限於 Laravel 9.x 使用,單 Laravel 也協助了 Soketi —— 使用 Node.js 撰寫的相容於 Laravel Echo 的 Web Socket 伺服器 ——提供說明文件。Soketi 提供了良好且開源的 Pusher 與 Ably 替代方案,可供偏好自行管理 Web Socket 伺服器的專案使用。

更多關於 Soketi 的資訊,請參考廣播說明文件Soketi 的說明文件

改進了 IDE 對 Collection 的支援

針對 Collection 的 IDE 支援改進由 Nuno Maduro 參與貢獻

Laravel 9.x 在 Collection 元件上新增了改進過的、「泛型(Generic)」風格的型別定義,提升了對 IDE 與靜態檢查的支援。如 PHPStorm 等 IDE 或 PHPStan 等靜態檢查工具現在可以原生地更理解 Laravel Collection 了。

新的輔助函式

Laravel 9.x 提供了兩個新的方便輔助函式,可以讓你在你自己的專案內使用。

str

str 會為給定的字串回傳一個 Illuminate\Support\Stringable。這個函式與 Str::of 方法等價:

1$string = str('Taylor')->append(' Otwell');
2 
3// 'Taylor Otwell'
1$string = str('Taylor')->append(' Otwell');
2 
3// 'Taylor Otwell'

若沒有提供引數給 str 函式,則 str 會回傳一個 Illuminate\Support\Str 的實體:

1$snake = str()->snake('LaravelFramework');
2 
3// 'laravel_framework'
1$snake = str()->snake('LaravelFramework');
2 
3// 'laravel_framework'

to_route

to_route 方法會產生一個跳轉到給定命名路由的重新導向 HTTP 回應,讓我們能在路由與 Controller 中以更富語意的方法跳轉到命名路由:

1return to_route('users.show', ['user' => 1]);
1return to_route('users.show', ['user' => 1]);

若有需要,也可以傳入一個用於跳轉的 HTTP 狀態碼以及一些額外的回應標頭作為 to_route 方法的第三與第四個引數:

1return to_route('users.show', ['user' => 1], 302, ['X-Framework' => 'Laravel']);
1return to_route('users.show', ['user' => 1], 302, ['X-Framework' => 'Laravel']);
翻譯進度
100% 已翻譯
更新時間:
2023年2月11日 下午12:59:00 [世界標準時間]
翻譯人員:
  • cornch
幫我們翻譯此頁

留言

尚無留言

“Laravel” is a Trademark of Taylor Otwell.
The source documentation is released under MIT license. See laravel/docs on GitHub for details.
The translated documentations are released under MIT license. See cornch/laravel-docs-l10n on GitHub for details.