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