消失的Pivot模型ID(Laravel踩坑日記)

前因

最近公司后端項目進行了改造升級,由之前的laravel5.6版本升級到了laravel5.8版本,升級后系統產生了不少sql執行錯誤,但是在老版本系統運行的好好的,于是就產生了今日的扒坑之旅。

推薦:《laravel教程

項目環境

老系統(linux + laravel5.6 + php7.2 + mysql5.7)

升級后新系統(linux +laravel5.8 + php7.2 + mysql5.7)

只單純升級了laravel框架版本,并無升級其他相關服務依賴.

但是卻出現大量的SQL執行錯誤,異常監控如下:

消失的Pivot模型ID(Laravel踩坑日記)

分析過程

導致這段服務出錯的是這樣的一段業務邏輯,下面通過一段demo來模擬.

$pivot?=?UserRole::firstOrCreate([ ????'user_id'?=>?3, ????'role_id'?=>?3, ]); $this->addRoleHistory($user,$pivot->id); dd($pivot->id);

在laravel5.6版本中這段代碼運行起來毫無問題,但升級到5.8版本中就會引發大量的SQL執行錯誤,就像下面這樣.

laravel5.6: ????dd($pivot->id);?//10002 laravel5.8: ????dd($pivot->id);?//null

在5.6中保存中的數據還能正常獲取到ID,在5.8中怎么就不行了呢,于是馬上去查看了laravel5.8的發行說明,也沒有發現對Pivot模型取消獲取自增ID的改動,于是開始進行5.8源碼查閱。。。

首先對5.6和5.8的firstOrCreate函數進行了對比,發現無改動,代碼邏輯執行無誤。

消失的Pivot模型ID(Laravel踩坑日記)

然后繼續翻閱model->save()函數的代碼

,發現不存在的數據是通過insertAndSetId該函數插入數據并設置主鍵ID

消失的Pivot模型ID(Laravel踩坑日記)

但insertAndSetId函數又是通過incrementing這樣的一個成員屬性來控制的,屬性的默認值是true

消失的Pivot模型ID(Laravel踩坑日記)

當這個屬性變更時就不會執行者一步驟,難道這個成員屬性在被操作過了?

于是立馬查看了5.8的pivot模型源碼.

消失的Pivot模型ID(Laravel踩坑日記)

最終發現是5.8的在中間表Pivot class默認將incrementing設置成了false,所以數據被成功插入,但是沒有設置插入后的主鍵ID,造成剩余服務崩潰,沒能正常運行…

修復方案

在每個Pivot Class中重新覆蓋掉incrementing屬性值為true即可.

class?UserRole?extends?Pivot { ????public?$incrementing?=?true; ????protected?$fillable?=?[ ????????'user_id', ????????'role_id', ????]; }

修復后:

laravel5.8: ????dd($pivot->id);?//10003

后記

于是又去仔細看了一遍laravel5.7~laravel5.8發行說明,發現依然沒有提到這個改動的原因,于是又去google了一遍,依然沒有找到這個梗的原因所在.

消失的Pivot模型ID(Laravel踩坑日記)

最后還是成功修復掉了該處改動帶來的問題,也提醒了我們在后續版本升級時還是需要多注重UT的覆蓋及版本兼容改動測試,多個維度來保證項目質量。

? 版權聲明
THE END
喜歡就支持一下吧
點贊7 分享