この記事ではfillbleの使い方について紹介していきます。
Laravelでデータベースの情報更新や追加を行う際にfillableの設定をしておくと、より安全でシンプルなコードで開発をすることができるようになります。
どういった仕組みでどのような効果があるのか、実例のコードを使って紹介していきたいと思います。
この記事を読むメリット
- fillableの基本的な使い方が分かる
- セキュリティ対策しながらシンプルなコードでデータベース操作ができるようになる
複数代入の脆弱性とは
まず、fillableの使い方を紹介する前に複数代入の脆弱性について実例を使って紹介します。
この脆弱性が理解できるとfillableの必要性がより理解しやすくなるかと思います。
プロフィール編集画面での例
どういうことか、ユーザー情報の更新処理を例に説明します。
usersテーブルは以下のようになっています。
mysql> show columns from users;
+-------------------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+-----------------+------+-----+---------+----------------+
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| email | varchar(255) | NO | UNI | NULL | |
| email_verified_at | timestamp | YES | | NULL | |
| password | varchar(255) | NO | | NULL | |
| remember_token | varchar(100) | YES | | NULL | |
| level | int unsigned | NO | 1 | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
+-------------------+-----------------+------+-----+---------+----------------+
そして以下画像はプロフィール編集画面を想定しています。
ユーザー名、メールアドレスを編集できるようになっています。
そしてその下にそのユーザーのレベルが表示されている状態です。
そして投稿した内容を保存する処理が以下になります。
public function update(Request $request, User $user)
{
$user->update($request->all());
return redirect()->route('user.edit', ['user' => $user]);
}
フォームで入力した内容をまとめて更新するために「$user->fill($request->all())->save();」という処理をしています。
これは複数代入というもので、POSTして送られてくるname属性と保存するデータベースのカラム名を合わせることでまとめて更新処理ができる機能です。
先ほどのプロフィール編集の例で考えると、名前とメールアドレスの変更をまとめて処理してくれます。
これ自体はコードの記述量を抑えることができてとても便利なものです。
予期しないデータまで書き換えられてしまうリスク
しかし、悪意のあるユーザーがこの仕組みを悪用するリスクがあります。
POSTで送られてくるデータ「$request->all()」をまとめて保存していました。
しかし、その中にフォームで入力していたユーザー名、メールアドレス以外のデータが紛れ込んでしまったらどうなるでしょうか。
ユーザーには直接編集されたくない情報まで更新されてしまうリスクがあります。
例えばユーザーのレベルのカラム名を推測され、その値をPOST通信の中に入れられて送信されてしまった場合、不当に更新されてしまいます。
複数代入は、POST通信で送られてきた内容をまとめて保存・更新できて便利ですが、このように意図しない情報まで更新されてしまうリスクがあります。
エンジニアにおすすめ書籍
エンジニアになりたて、これから勉強を深めていきたいという方におすすめの書籍はこちら!
Laeravelではデフォルトで複数代入の脆弱性の対策が取られている
そういったリスクを回避するために、Laravelではデフォルトで対策が取られています。
それが「fillable」です。
複数代入を行うメソッドに適用されます。
fillableをModelに設定をすることで、設定されたカラムのみが更新ができるようになっています。
fillableの設定
設定方法は以下のようになります。
protected $fillable = [
'name',
'email',
'password',
];
User.php内にこのようにfillableの設定をします。
制限をかけたいカラム名を配列の中に入れていきます。
これで複数代入を行うメソッドに制限をかけることができます。
複数代入ができるメソッド
では複数代入ができるメソッドはどんなものがあるのか紹介します。
以下に紹介するものを使用するとfillableが適用され、設定されたカラムのみが更新されるようになります。
- create()
- update()
- fill()->save()
どのメソッドもまとめて保存、更新ができるようなメソッドになっています。
これらのメソッドを使うと、fillableに設定したカラムしか更新が効かなくなります。
fillableに設定したくないカラムの更新は個別で指定してsave()
ではセキュリティ面でfillableに設定したカラムを更新するにはどうするか。
答えは、save()を使って個別更新を行います。
// ユーザーレベル+1
private function updateUserLevel($user)
{
$user->level++;
$user->save();
}
こちらはlevelカラムの値に1加えて保存する処理です。
このように個別でカラムを指定してsave()をすると、fillableの制約から外れて保存することができます。
fillableを使ってより安全なデータ更新を行う
いかがだったでしょうか。
fillableの役割と使い所が理解できたかと思います。
新しいカラムを追加した際に、fillableへの追加をしないとデータが更新されないといった沼にハマりかねないのでそこは注意が必要です。
私はそれで長い時間原因が分からず苦労した思い出があります。(笑)
fillableを使ってより安全にデータ更新ができるようになりましょう。
そしてデータ更新の方法とそれぞれの違いを理解しておくと適切なメソッドを選択できるようになりますので整理しておくと良いと思います。