hero_picture
Cover Image for LaravelのPivotのincrementingがfalseになっていた件

LaravelのPivotのincrementingがfalseになっていた件

2019/09/27

みなさま、初めまして。

WEB事業部の李です。 どうぞよろしくお願いいたします。

最近、カップヌードルの味噌味にハマっています。

昼は基本おむすびです。

www.nissin.com

本題

さて、本日は、

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;
3456$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を取得出来ていたのですね。

github.com

ちなみに、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ご参考ください。

github.com

以上です。

すでに6.xがLTSとなってますが、Pivotクラスのincrementingプロパティのデフォルトはfalseになっていますので、

この記事が皆様のご参考になればと思います。