今回は「マスアサインメントの保護を外す」という大胆なタイトルです。マスアサインメントの保護は、Eloquentにおけるモデルの定義においての$fillableや$guardedを通しての設定のことです。その保護を外す、とは、これを指定しない、ということではなく(もちろん外すのは危険)、あるケースにおいて外す必要が出てきたときに、どう外すかということです。
$fillable & $guarded
復習として、Eloquentにおけるこれらの変数の説明から始めます。
Laravelのプロジェクトのデフォルト設定のDBのusersのテーブルは以下のような構造です。
mysql> describe users; +-------------------+---------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------------+---------------------+------+-----+---------+----------------+ | id | bigint(20) 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 | | | created_at | timestamp | YES | | NULL | | | updated_at | timestamp | YES | | NULL | | +-------------------+---------------------+------+-----+---------+----------------+
そして、EloquentのモデルのUserでは、以下のように$fillableが定義されています。
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
つまり、name, email, password以外の項目、例えば、idとかとともにマスアサインしても、以下のようにUserのインスタンスの作成時には弾かれる、ということです。
$ php artisan tinker
>>> $input = ['id' => 1, 'name' => 'test', 'email' => 'test@example.com'];
=> [
"id" => 1,
"name" => "test",
"email" => "test@example.com",
]
>>> new User($input);
[!] Aliasing 'User' to 'App\User' for this Tinker session.
=> App\User {#2985
name: "test",
email: "test@example.com",
}
>>>
作成されたインスタンスにおいては、idの項目はありません。fill()を使用しても同じことです。
>>> $user = new User();
=> App\User {#2984}
>>> $user->fill($input);
=> App\User {#2984
name: "test",
email: "test@example.com",
}
>>>
そして、$fillableでなく、$guardedを使用しても結果は同じことです。
...
// protected $fillable = [
// 'name', 'email', 'password',
// ];
protected $guarded = [
'id', 'email_verified_at', 'remember_token', 'created_at', 'updated_at'
];
...
保護を外す
さて、上の$fillableの保護指定をそのままにして、同じUserのモデルでidなど、name, email, password以外の項目を指定してインスタンスを作成したいときは、どうするのでしょう?
そこで登場するのが、unguard()のメソッドです。
>>> User::unguard()
=> null
>>> new User($input);
=> App\User {#2985
id: 1,
name: "test",
email: "test@example.com",
}
>>> $user = new User();
=> App\User {#2986}
>>> $user->fill($input);
=> App\User {#2986
id: 1,
name: "test",
email: "test@example.com",
}
idが入るようになりましたね。
解除するには、unguard(false)です。
>>> User::unguard(false);
=> null
>>> new User($input);
=> App\User {#2987
name: "test",
email: "test@example.com",
}
>>>
以前のようにもうidは入りません。
unguard()はセッションで有効ですが、1つのインスタンスで保護を外すには、forceFill()を使用できます。
>>> $user = new User();
=> App\User {#2985}
>>> $user->forceFill($input);
=> App\User {#2985
id: 1,
name: "test",
email: "test@example.com",
}
メルマガ購読の申し込みはこちらから。
