環境
- windows10
- DockerDesktop for Win 3.5.x
- Laravel 8.x
- PHP 8.x
- VsCode
- gitbash 2.32.0.1
この記事は何?
本記事では、Laravelのcreate、saveの使い分け、違いについて説明しています。
(バージョンによる差異はそこまで無いかと思います。)
複数代入保護
- Laravelを用いてDB にデータを保存する際、Eloquent (エロクアント)を使用することで効率よくコードを書くことができますが、前提として、複数代入保護というセキュリティ保護の概念を理解しておく必要があります
- 複数代入は、ユーザーからの入力を元にDBへデータを保存する際、悪意のあるユーザーがこちらの意図しないデータの保存・更新を行うように複数の項目を代入してくることです
- 具体例)
悪意のあるユーザーが独自に項目を追加しPOSTすることで、管理者権限に昇格される等 - Laravelでは複数代入保護のため、以下のようにどちらかの形式でモデルファイルにプロパティ(カラム)を設定しておく必要があります。
- $fillableでレコードを追加して良いカラムを設定(ホワイトリスト形式)
- $guardedで、レコードを追加しはいけないカラムを設定(ブラックリスト形式)
保存方法
ようやく本題ですが、複数代入の保護を遵守しつつ、Eloquent でモデルインスタンスを作成して保存する方法はざっくりと以下の2種類に分けられます。(厳密には他にも複数あるが、セキュリティ保護・使いやすさの観点から2つのみ紹介)
- create
- fill + save
create
モデルクラスから create メソッドを呼ぶことで、以下の一連の処理を一気に行ってくれます。
処理内容
インスタンスの作成
↓
データの保存
↓
作成したインスタンスをreturnする
書き方
モデルファイル
// モデルでfillableかguardedのどちらかを指定する必要あり
protected $fillable = ['recipe_name'];
// protected $guarded = ['recipe_name'];
コントローラー
$recipe = App\Recipe::create(['recipe_name' => 'カレーライス']);
注意点
create()の引数は配列型で渡す必要があるため、注意
fill + save
newでインスタンスを作成し、属性の代入を fill メソッドで保護しつつ、DB への保存を save メソッドでといくつかの処理に分けて行う。
書き方
モデルファイル
// 1.createと同様、モデルファイルにfillableかguardedのどちらかを指定する必要あり
protected $fillable = ['recipe_name'];
// protected $guarded = ['recipe_name'];
コントローラー
$recipe = new App\Recipe();
$recipe->fill(['recipe_name' => 'カレーライス']);
$recipe->save();
// or
// モデルファイルに設定しているプロパティとリクエストの内容が一致していれば、ワンライナーで書くことも可
$recipe->fill($request->all())->save();
fill + saveは、インスタンスは作成したいがDB への保存は処理を分けたいなどの際に使用される。また、createメソッドと同じく複数代入保護のため、fillable か guarded を指定する。
個人的な見解
基本的には create メソッドを使用していれば、セキュリティ面でも、保守性の観点でも間違い無いかと思います。
コメント
[…] 「->fill」と「->save」はこの記事に解説があります。 […]