初めてのLaravel 5.1 : (11) Eloquent マスアサインメント

Eloguent のマスアサインメント機能を使って、テーブルにデータを追加してみます。
下記の create() メソッドに配列で値を渡すことで、1文でテーブルにデータを追加することができます。

App\Article::create(['title' => '3件目の記事', 'body' => '吾輩は猫である', 'published_at' => Carbon\Carbon::now()]);

では、tinker を使って実際にやってみます。

$ php artisan tinker

>>> App\Article::create(['title' => '3件目の記事', 'body' => '吾輩は猫である', 'published_at' => Carbon\Carbon::now()]);
Illuminate\Database\Eloquent\MassAssignmentException with message 'title'

何やら、MassAssignmentException という例外エラーが発生しました。

実はEloquentのマスアサインメントでは事前に登録できる項目を宣言しておく必要があります。下記のようにモデルの fillable 変数に配列で宣言します。

<?php namespace App;
// app/Article.php

use Illuminate\Database\Eloquent\Model;

class Article extends Model {
	
	protected $fillable = ['title', 'body', 'published_at'];
	
}

もう一度、tinker でやってみます。
tinker は再起動してください。

$ php artisan tinker

>>>  App\Article::create(['title' => '3件目の記事', 'body' => '吾輩は猫である', 'published_at' => Carbon\Carbon::now()]);
=>  {
       title: "3件目の記事",
       body: "吾輩は猫である",
       published_at:  {
           date: "2015-06-18 08:14:06.000000",
           timezone_type: 3,
           timezone: "UTC"
       },
       updated_at: "2015-06-18 08:14:06",
       created_at: "2015-06-18 08:14:06",
       id: 2
   }
>>> App\Article::all()->toArray();
=> [
       [
           "id"           => "1",
           "title"        => "はじめてのタイトル",
           "body"         => "かくかくしかじか",
           "created_at"   => "2015-02-22 21:08:16",
           "updated_at"   => "2015-02-22 21:08:16",
           "published_at" => "2015-02-22 20:47:07"
       ],
       [
           "id"           => "2",
           "title"        => "3件目の記事",
           "body"         => "吾輩は猫である",
           "created_at"   => "2015-02-23 16:32:31",
           "updated_at"   => "2015-02-23 16:32:31",
           "published_at" => "2015-02-23 16:32:31"
       ]
   ]

今度は上手く行きました!


マスアサインメントのセキュリティー対策

では何故、マスアサインメントでは、このように fillable を使って、ガードする必要があるのでしょうか?

マスアサインメントは、ユーザからのリクエストをテーブルに保存する処理で使用されます。リクエストに想定していな項目が含まれていた場合、そのまま更新されてしまうと、重大なセキュリティーホールとなってしまうためです。

例えばUserクラスに name, age, admin の3カラムがあり、adminはユーザーの画面からは更新させない管理者権限だとします。Userの新規登録処理で、以下のようなコードを書いていた場合…

$article = AppUser::create($request->all());

不正リクエストなどによって$requestにadminが含まれていた場合、管理者権限を任意の値に設定されてしまいます。

その為、マスアサインメントでは fillableで宣言した項目のみに許可を与え、それ以外をガードしているのです。

http://laravel.com/docs/5.1/eloquent#mass-assignment

初めてのLaravel 5.1 : (11) Eloquent マスアサインメント」への2件のフィードバック

  1. Kang Yoosam より:

    いつも拝見させていただいております。非常に助かってます。

    モデルにfillableを宣言したあとに、tinker を再起動しなければならないことを言及しておくとより良いと思います。僕はそこで詰まってしまいました笑

    いつもありがとうございます。これからも「ララ帳」更新をよろしくお願いします。

    いいね

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中