今回は「マスアサインメントの保護を外す」という大胆なタイトルです。マスアサインメントの保護は、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", }メルマガ購読の申し込みはこちらから。