🤢

Laravelでinsertを使うべきでない理由

2021/08/25に公開

Laravelでバルクインサートをしようとすると、「insert」メソッドを使う以外に方法はありません。

なので、複数のレコードを一気に入れたい場合はinsertメソッドは結構便利なのですが、
なかなか厄介なデメリットは結構多いです。

デメリット1. fillを通さないためエラーが起きやすい

データベースを更新するものとして、例えば「create」や「update」や「save」などのメソッドがありますが、これらは全部内部的に fill メソッドというものを呼び出しています。

fillメソッドは、 「Modelに記載するfillable の配列の中にあるカラムだけを更新するもしくは、guardedに記載されていないカラムだけを更新する」というものです。

insertはこのfillメソッドを呼び出していないのです。

つまりどういうことかというと、 usersテーブルに「id, name, email, password」 というカラムがあった場合に「id, name, email, password, password_confirmation」を更新するぜ!と言った場合は「password_confirmation」なんてカラムはねえよーってエラーで弾き返されます。DBに存在するカラムを全てきちんと教えてあげないとすぐにエラーが発生してしまうのです。

↑「じゃあ、ちゃんと指定してあげればいいやん(笑)」っていうツッコミがきそうなので補足しておくと、
Laravelのアクセサを使用して、本来DBに存在しない項目をコレクションに持たせておくことができたり、システム都合で本来DBに保存しない項目をコレクションに持たせておくことはよくあります。
それをいちいちisnertメソッドを発動する前に取り除くロジックを書かなければいけないのが面倒で、エラーが出やすく扱いが大変なのです。

デメリット2. タイムスタンプが更新されない

insertでは created_atupdated_at のタイムスタンプは更新されません。
なので、もし更新したい場合は ObserverなどでDB更新を検知するか、insertメソッドを呼び出す前に、DBに入れたいデータの中に created_at => now()updated_at=>now() のように自分で追加する必要があります。
これも面倒くさい。(笑)

終わりに

一番のデメリットはやはりDBに存在しないカラムを追加しようとするとエラーになることかなと思います。
シーダーの時とかには使えるかもしれませんが、結構DBに入れる値が変動的になるような実際のシステムの一部としては使わない方がいいかなと思います。

基本的には create update saveとかを使用して、リレーショナルデータを一気に作成したい場合は createMany を使ったりしてみてください。

なんか終始上手く伝えられていないような気がしますが、こんな感じです!

Discussion