サイトアイコン 上尾市のWEBプログラマーによるブログ

[Laravel] fillableが効かない原因(無視されるメソッドと無視されないメソッド)

Laravel

概要

Laravelではモデルの$fillable配列でマスアサインメントを許可するカラムを指定することができる。
しかし、登録・更新に使用するメソッドによって無視される場合と無視されない場合があるため、注意が必要である。

結論

同じ名前のupdateメソッドでも、モデルのupdateメソッドはfilableが有効となり、クエリビルダのupdateメソッドはfilableが無視されてしまう。

よって、クエリビルダのudpateの使用は避けた方がよいと思われる。
ただし、そのためには使用しているのがモデルのメソッドなのか、クエリビルダのメソッドなのか、をしっかりと把握する必要がある。

また、saveメソッドを使う場合は、必ずfillメソッドで値をセットするべきである。

サンプルfillableが効く・無視されない
(データが保存されない)
Item::create(['name' => 'hoge']);
Item::find(1)->update(['name' => 'hoge']);
Item::where(['id' => 1])->first()->update(['name' => 'hoge']);
Item::find(1)->fill(['name' => 'hoge'])->save();
Item::updateOrCreate(['id'=>1, 'name'=>'hogehoge'])
Item::where(['id' => 1])->update(['name' => 'hoge']);×
Item::query()->where(['id' => 1])->update(['name' => 'hoge']);×
DB::table('items')->where(['id' => 1])->update(['name' => 'hoge']);×
$model = Item::find(1);
$model->name = 'hoge';
$model->save();
×
カラム名「name」が$fillable配列に含まれていない場合の挙動

fillableが効く・無視されない(データが保存されない)メソッド

クエリビルダ(Illuminate\Database\Eloquent\Builder)のインスタンスメソッドcreate

Item::create(['name' => 'hoge']); // 'hoge'は保存されない

モデルのインスタンスメソッドupdate

Item::find(1)->update(['name' => 'hoge']); // 'hoge'は保存されない

Item::where(['id' => 1])->first()->update(['name' => 'hoge']); // 'hoge'は保存されない

モデルのインスタンスメソッドsave(fillメソッドを使う場合)

$model = Item::find(1);
$model->fill(['name' => 'hoge']) // 'hoge'はセットされない
$model->save(); // 'hoge'は保存されない

クエリビルダ(Illuminate\Database\Eloquent\Builder)のインスタンスメソッドupdateOrCreate

Item::updateOrCreate(['id'=>1, 'name'=>'hoge']); // 'hoge'は保存されない

fillableが効かない・無視される(データが保存される)メソッド

クエリビルダ(Illuminate\Database\Eloquent\Builder)のインスタンスメソッドupdate

Item::where(['id' => 1])->update(['name' => 'hoge']); // 'hoge'は保存される

// query()を使う場合
Item::query()->where(['id' => 1])->update(['name' => 'hoge']); // 'hoge'は保存される

クエリビルダ(\Illuminate\Database\Query\Builder)のインスタンスメソッドupdate

DB::table('items')->where(['id' => 1])->update(['name' => 'hoge']); // 'hoge'は保存される

モデルのインスタンスメソッドsave(fillメソッドを使わない場合)

$model = Item::find(1);
$model->name = 'hoge';
$model->save(); // 'hoge'は保存される
モバイルバージョンを終了