將部落格的 Laravel 版本從 6 升級至 7,當中所遇到的問題
花了點時間,將部落格的 Laravel 版本升級至 7。
原本想說反正 8 也快出來了, 不如直接 6 跳 8 (錯誤示範,官方建議是一版一版慢慢升級),省得升級兩次,麻煩,不過 Laravel 新版本推出的時候,可能會有套件突然無法支援的情況,所以如果就算 8 出來,建議還是觀望一下比較好,太早升級,可能就是第一批白老鼠。
基本上 Laravel 的升版有以下兩種方式。
- 跟著官方文件,一步一步修改受影響的地方。
- 土法煉鋼,直接開一個新專案重新寫。
一般當然是使用第一種,不過由於此部落格是小型專案,開一個重新寫其實沒什麼問題 (誤),大型的多人協作專案,如果你提議要重新寫一個,我想其他人的反應一定會是…
這次部落格 6 升級 7的過程算是非常順利,唯一有一個需要注意的點,就是對時間格式的更改,Laravel 中的 Carbon 套件的預設時間格式轉成 ISO-8601。
原本的格式是 2019-12-02 20:01:00。
現在改為 2019-12-02T20:01:00.283041Z。
如果 faker 中使用 now()
這樣的方法,就會因為時間儲存格式不符合資料庫格式而發生錯誤。雖然文件中特別備註不影響資料儲存,但是當你使用 seed 填充假資料的時候,有可能就會發生時間格式上錯誤。
$ php artisan migrate:refresh --seed
PDOException::("SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: '2020-03-24T23:36:15.000000Z' for column `weibo`.`users`.`email_verified_at` at row 1")
論壇也有人遇到類似的事情:https://learnku.com/laravel/t/42337。
其實官方也有說明,如果你想使用舊的時間格式,只要覆寫 serializeDate 方法就好,那具體要怎麼做呢?
就是在每個需要填入數據的 Model 加上以下這一段。
use DateTimeInterface;
protected function serializeDate(DateTimeInterface $date)
{
return $date->format('Y-m-d H:i:s');
}
一開始我就是這麼做,但後來想想,這好像不符合 DRY (Don’t Repeat Yourself) 原則,所以上網研究一下,並換了一種方式。
首先,我的 Model 全部都是放在 app/Models
這個資料夾底下,因此我先在這邊再創一個資料夾 Traits
。
並在裡面新增一個檔案 SerializeDate.php,內容如下。
<?php
namespace App\Models\Traits;
use DateTimeInterface;
// 因 Laravel 7 調整了時間格式會導致 seeding 出錯,這裡對 serializeDate() 進行覆寫
trait SerializeDate
{
/**
* Prepare a date for array / JSON serialization.
*
* @param \DateTimeInterface $date
* @return string
*/
protected function serializeDate(DateTimeInterface $date)
{
return $date->format('Y-m-d H:i:s');
}
}
這樣如果 User Model 需要調整時間格式,只要在 User.php 加入一行。
// trait SerializeDate
use Traits\SerializeDate;
就大功告成拉!