かなで技術日誌

プログラミングやエンジニアリング周りについて

主なアウトプットはScrapboxObsidianにまとめてます。

Eloquent Model FactoryでMaximum function nesting level of '256' reached, aborting!

Eloquentのfactoryでテストデータを用意してテストを実行した際、以下のようなエラーが突如発生した。

PHP Fatal error:  Maximum function nesting level of '256' reached, aborting! path/to/vendor ...

結論

依存関係が循環するfactoryを定義して実行しており、factoryの実行自体でエラーにならなかったため。

内容

これは大量の再帰呼び出しを行った際に発生するエラーです。 再帰呼び出しの回数が非常に多い場合、メモリにひたすら実行された処理の結果が積み重ねられ、スタックオーバーフローが発生する可能性があるため、PHPでは一定回数を超えるとエラーが発生します。

このエラーになる回数自体はXDebugの設定で変更できます。

teratail.com

ですが、今回テスト対象の実装には再帰呼び出しもなければ大量のループもありませんでした。 本当の原因はエラーの原因はfactoryの実装で以下のような実装になっていました。

factory(Room::class, function(Faker $faker){
    return [
        'name' => 'room name',
        'house_id' => factory(House::class)->create()->id
    ];
});
factory(House::class, function(Faker $faker){
    return [
        'name' => 'house name',
        'room_id' => factory(Room::class)->create()->id
    ];
});

RoomモデルとHouseモデルが循環しており、実質無限に再帰的に相互で呼び出しを行う処理が作られていました。
しかし、Houseモデルが参照しているhousesテーブルにはroom_idは存在しません。 存在しないカラムをfactoryで定義しているのでエラーになりそうですが、Eloquentのfactoryでは存在しないカラム自体ではエラーにならず、今回のエラーになるまでずっと処理が止まらなかったということです。

想定していなかった動作だったので原因の発見に少し時間がかかりました。 個人的には存在しないカラムを定義しているのであればエラーを発生させて欲しいですね。