みなさま、初めまして。
WEB事業部の李です。 どうぞよろしくお願いいたします。
最近、カップヌードルの味噌味にハマっています。
昼は基本おむすびです。
本題
さて、本日は、
Laravelを5.6から5.8にアップグレードした際に、
Pivotクラスのidをデフォルトでは取得できなかった話を書きたいと思います。
結論
先に結論ですが、LaravelのPivotのincrementingが5.8からdefaultでfalseに設定されていたためでした。
trueにオーバーライドすると取れました。
オーバーライドもどうだろうというのはありますが。。
経緯など詳細
Laravelのバージョンが5.6の時に、中間テーブルを複数またぐような構造のデータを作成する必要がありました。
実装としては、pivotクラスのormを利用して登録後のidを取得し、さらに中間テーブルを作成するというプログラムが既に作られていました。
1モデル->Hoge(※中間テーブル)->Hoge2(※中間テーブル)->….
上の例で、Hoge2に、Hogeのidを登録するという流れですが、
5.8へアップグレードするとhogeのレコードを作成後idが取れなくなっていました。。。
※Hogeのidは、auto_incrementで定義されています。
1$hoge = Hoge::create($data); // $hoge->id 取れない。。
2$hoge = new Hoge;
3・
4・
5・
6$hoge->save(); // $hoge->id 取れない。。
7
まじかよ。。と、もう一度アップグレードガイドを見たりしたのですが、
特に記述はなく、あの手この手と試してみたりしてたのですが、やはり取れず。。
まさかのlastInsertIdメソッド記述しないといけないのかと若干気持ちが沈んでいた頃、
あるエンジニアの方から、もしかしてこれじゃないですか?と指摘を受け、
venderの方のpivotクラスをのぞいてみると、
1public $incrementing = false;
2
の記述がありました。
そこで、Modelクラスのsaveメソッドを少し追いかけてみると、ありました。
performInsertメソッド!これやん!!と。。
この中で、下記のような記述がありました。
1//・・・省略
2// If the model has an incrementing key, we can use the "insertGetId" method on
3// the query builder, which will give us back the final inserted ID for this
4// table from the database. Not all tables have to be incrementing though.
5$attributes = $this->getAttributes();
6if ($this->getIncrementing()) {
7$this->insertAndSetId($query, $attributes);
8}
9// If the table isn't incrementing we'll simply insert these attributes as they
10// are. These attribute arrays must contain an "id" column previously placed
11// there by the developer as the manually determined key for these models.
12else {
13if (empty($attributes)) {
14return true;
15}
16$query->insert($attributes);
17}
18//・・・省略
19
“which will give us back the final inserted ID”<-まさにですね。
getIncrementingメソッドは下記のような記述でした。
1public function getIncrementing()
2{
3return $this->incrementing;
4}
5
念の為、Laravelframeworkリポジトリで、バージョン5.6のpivotクラスを見てみると、
incrementingプロパティの記述がありません。
PivotクラスはModelクラスを継承しており、Modelクラスのプロパティには、$incrementing=trueとあったので、
バージョン5.6では、idを取得出来ていたのですね。
ちなみに、create()メソッドは、Illuminate\Database\Eloquent\Builderクラスのcreateメソッドで、結局saveを使っているみたいです。
1public function create(array $attributes = [])
2{
3return tap($this->newModelInstance($attributes), function ($instance) {
4$instance->save();
5});
6}
7
というわけで、問題のHogeクラスに、
1public $incrementing = true;
2
と、オーバーライドするとidが取れるようになりました。
frameworkでの詳しい経緯は下記のPRご参考ください。
以上です。
すでに6.xがLTSとなってますが、Pivotクラスのincrementingプロパティのデフォルトはfalseになっていますので、
この記事が皆様のご参考になればと思います。