概要
Laravelで、モデルから新しいレコードを生成し保存するメソッドとして、firstOrNew
メソッドを使用しているのですが、MassAssignmentException
エラーが発生して使用できないという問題があったので、その時の対応を備忘録として記します。
firstOrNewメソッドとは
Laravelの公式ドキュメントには以下のように書かれています。
http://readouble.com/laravel/5/1/ja/eloquent.html#inserting-and-updating-models
firstOrNewメソッドもfirstOrCreateのように指定された属性にマッチするデータベースのレコードを見つけようとします。しかしモデルが見つからない場合、新しいモデルインスタンスが返されます。firstOrNewが返すモデルはデータベースに保存されていないことに注目です。保存するにはsaveメソッドを呼び出す必要があります。
以下のように指定することで、条件に合うレコードが存在すればfirst()
メソッドで最初の1件を取得し、存在しなければ新しいインスタンスを取得する、というメソッドです。
// 属性のフライトか、存在しなければ新しいインスタンスを取得する…
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);
MassAssignmentExceptionエラーの発生
このfirstOrNew()
メソッドを利用している箇所が動作せず、MassAssignmentException
エラーが発生していました。
ずっと原因がわからなかったのですが、調べてみると、save()
やcreate()
メソッドを使用するときは、モデルに$fillable
か$guarded
属性のどちらかを設定しなければいけないようでした。
公式ドキュメントをよく見ると以下のように書いてあります。
http://readouble.com/laravel/5/1/ja/eloquent.html#inserting-and-updating-models
一行だけで新しいモデルを保存するにはcreateメソッドが利用できます。挿入されたモデルインスタンスがメソッドから返されます。しかしこれを利用する前にEloquentモデルを複数代入から保護するために、モデルへfillableかguarded属性のどちらかを設定する必要があります。
$guarded
には絶対に変更しないカラムを、$fillable
には変更するかもしれないカラムを設定する必要があります。
以下の記述を対象のモデルに追加することで、firstOrNew()
を実行することができました
// 絶対に変更しないカラム
protected $guarded = ['id'];