Laravel

What’s new in Laravel 8 — part 1

Azole (小賴)
9 min readSep 24, 2020

自從 Laravel 6 開始遵循 Sematic Versioning 後,版本號就咻咻咻的跳,記得在 7 月準備 laravel conf 的分享時,才 7.21.0,然後九月 Laravel 8 就釋出了,是不是覺得很興奮開心(倍感壓力)啊?

興奮歸興奮,還是要冷靜一下,來看看 Laravel 8 有哪些好玩的新功能,這次就先分享以下五個,我自己看過之後,覺得 Laravel 果然又更方便好用了呢!

  • Models 檔案夾
  • Migration Squashing
  • Model Factory Classes
  • Model Factory Relationships
  • Maintenance Mode

Models 檔案夾

Models 檔案夾

千呼萬喚始出來!以我自己來說,我習慣不把 models 放在 app 檔案夾裡,雖然說我的 laravel 專案有另外的模組化設計,所以也很少會有獨立、不在模組中的 model,但如果有,我是一定會開一個 Models 檔案夾的,現在終於有了。

Laravel 8 也很貼心,如果不習慣有這個檔案夾存在,可以把它移除,之後當你 make:model 的時候,他也會自動幫你在 app/ 底下建立 model,以下程式碼就是在 make:model 時,檢查是否有 app/Models 檔案夾的實作 :

Illuminate/Foundation/Console/ModelMakeCommand.php

Migration Squashing

不知道大家在用 Laravel 時,有沒有遇過隨著專案需求的更迭、系統的長大,專案中的 migration 檔案愈來愈多,也愈來愈不好管理。如果整合測試環境中,需要每次都重新 migrate,因為 migration 的數量很多,也會因此而佔去不少時間?

Laravel 8 看到大家的痛苦了,新增了一個功能 php artisan schema:dump ,執行這個指令過後可以看到在 database 底下多了一個 schema 的檔案夾,且其中產生了一個叫做 {connection-name}-schema.sql 的檔案。以我的測試為例,connection name 為 mysql,所以被產生的檔案就是 /database/schema/mysql-schema.sql ,其內容就是資料庫 dump 出來的結果:

database/schema/msyql-schema.sql

如果在這之後又建立了新的 migration,在執行 migrate:fresh 時,laravel 將會先執行這個 schema sql 檔案,然後再執行新的 migration。

此外,也可以在建立這個檔案時加上 --prune ,他會在建立 schema檔案後,貼心地幫你移除整個 migrations 檔案夾,其實作如下:

Illuminate/Database/Console/DumpCommand.php

Model Factory Classes

在 Laravel 8 以前,要用 factory 建立資料,其用法如下:

factory(App\User::class)->make();
// or
factory('App\User')->make();

然後在 /database/factories 中,是用 $factory->define 來定義 factory 的。

在 Laravel 8,則將 factory 類別化了,一樣打開 /database/factories/UserFactory.php ,可以看到 UserFactory 已經變成一個 class 了,然後在 app/Models/User.php 中可以看到多用了一個 trait HasFactory ,然後就可以用以下方法來執行 factory:

App\Models\User::factory()->make();

這樣做有什麼好處呢?因為現在 factory 是一個類別,所以就變得很好擴展,例如 Factory States,按照文件中的範例,你可以在 factory class 中定義一個函式:

public function suspended()
{
return $this->state([
'account_status' => 'suspended',
]);
}

而在 definition 函式中,對 account_status 這個欄位可以給一個預設值,例如 active ,而當你想要建立出 account_statussuspended 的資料時,只需要在 make 前先叫用 suspended函式即可。

App\Models\User::factory()->suspended()->make();

當然,你可以定義不止一個 state,需要設定時就叫用,這樣在建立測試資料時,就增加了很多彈性。

Model Factory Relationships

在 Laravel 8 以前,如果 factory 要建立 relationship 的資料,例如在建立使用者時,為他建立關聯這個使用的文章,通常我們會這樣寫:

$users = factory(App\User::class, 3)
->create()
->each(function ($user) {
$user->posts()->save(factory(App\Post::class)->make());
});
// 或是$user->posts()->createMany(
factory(App\Post::class, 3)->make()->toArray()
);

但在 Laravel 8 中,只要 Model 中定義好關係,就可以用以下方法建立關聯資料:

$user = User::factory()
->has(Post::factory()->count(3))
->create();
// 甚至還提供了語法糖
$user = User::factory()
->hasPosts(3)
->create();

反過來也有對應的方式:

$posts = Post::factory()
->for(User::factory())
->count(3)
->create();
// 當然也有相對應的語法糖
$posts = Post::factory()
->forUser()
->count(3)
->create();

Maintenance Mode

在 Laravel 8 以前,維護模式提供了自定義訊息以及允許正常顯示的 IP,例如這樣:

php artisan down --message="Upgrading Database" --allow=127.0.0.1

Laravel 8 取消了 message 與 allow 這兩個設定,取而代之的是更彈性的擴充,例如白名單改為用 secret 來設定,而 message 則是用 render 來取代。

在啟動維護模式時,指定 secret:

php artisan down --secret="ilovelaravel"

然後開啟網站時,在網址加上這個 secret,例如 http://example.com/ilovelaravel ,可以發現網頁會被轉跳為 / ,且 cookie 中多了一個 laravel_maintenance ,如果將這個 cookie 手動刪掉,就會進入維護模式。

在 Laravel 8 啟動維護模式時,預設仍是 503 | SERVICE UNAVAILABLE ,在此之前,只能修改 message,也就是 SERVICE UNAVAILABLE 這一部分。但在 Laravel 8 可以透過 render 參數指定自己想要顯示的樣式,例如可以建立一個叫做 maintenance 的 blade,然後透過 render 來指定維護模式啟動時要顯示這個 blade。如果自己不想切版,Laravel 也很貼心的提供了一些 blade 讓我們用,只要 vendor publish 一下 laravel-errors 就可以使用了。

php artisan vendor:publish  // 選擇 laravel-errors

就可以在 views 中看到多了 errors 檔案夾:

然後在啟動維護模式時,指令採用自己想要用的頁面:

php artisan down --render="errors.illustrated-layout"

就可以看到換了一個新的維護模式畫面。當然,我們也可以自行去修改、編輯這些 Laravel 提供的頁面,是不是很方便呢?

errors.illustrated-layout

Laravel 8 的新功能不止這些,但先到此為止,有機會再分享 part2 (補充: 來了來了,在這裡),以下是這次分享的參考資料,蠻推薦看看的:

--

--

Azole (小賴)

As a passionate software engineer and dedicated technical instructor, I have a particular fondness for container technologies and AWS.