LaravelのMassAssignmentException


108

私はLaravelの初心者です。データベースをシードします。シードコマンドを実行すると例外が発生する

  [Illuminate\Database\Eloquent\MassAssignmentException]
  username



db:seed [--class[="..."]] [--database[="..."]]

何が悪いのでしょうか。私が使用するコマンドは:

php artisan db:seed --class="UsersTableSeeder"

私のシードクラスは次のとおりです:

class UsersTableSeeder extends Seeder {
    public function run()
    {
            User::truncate();
            User::create([
                'username' => 'PaulSheer',
                'email' => 'psheer@rute.co.za',
                'password' => '45678'
            ]);

            User::create([
                'username' => 'Stevo',
                'email' => 'steve@rute.co.za',
                'password' => '45678'
            ]);
    }
}

回答:


231

Laravel docのこのセクションを読んでください。 http //laravel.com/docs/eloquent#mass-assignment

Laravelはデフォルトで、大量割り当てのセキュリティ問題に対する保護を提供します。そのため、「マス割り当て」できるフィールドを手動で定義する必要があります。

class User extends Model
{
    protected $fillable = ['username', 'email', 'password'];
}

警告:passwordまたはなどの重要なフィールドの一括割り当てを許可する場合は注意してくださいrole。ユーザーが不要なときにこのフィールドの値を更新できるため、セキュリティの問題が発生する可能性があります。


7
-1これは機能しますが、Pascalculatorのソリューションは、アプリケーションの存続期間ではなく、大量割り当てが必要な場合にのみ警戒を解除するという点で優れています。
2014年

1
そうです、データベースシードの特定のコンテキストでは、シード中のみガードを解除する方が良いでしょう。ただし、この回答は参考トピックになりMassAssignmentExceptionそうであり、私の回答は優れた一般的な解決策であると考えるので、そのままにしておきます。
Alexandre Butynski、2015

アレクサンドル、あなたの論理に従うのは難しいと思います。同意する場合は、参照トピックになっているため、自分の回答を変更することもできます。あなたが提案した答えは確かに機能しますが、Laravel規約に準拠していません。
Pascalculator、2015

4
私はそれを良い一般的なパターンだと思うので(プロジェクトで使用しています)、Laravelの慣習にほぼ準拠しているとは考えていません(ドキュメントを参照)。しかし、複数の意見が素晴らしく、あなたの解決策は私のものと同じくらい良いので、私はそれを賛成し、他の人にそれを読むことを勧めます:)
Alexandre Butynski

'password' => bcrypt( '45678')
Douglas.Sesar

31

Laravel 4.2を使用しています。

あなたが見ているエラー

[Illuminate\Database\Eloquent\MassAssignmentException]
username

実際、データベースが一斉にいっぱいになることから保護されているためです。これは、シーダーを実行しているときに行っていることです。ただし、私の意見では、シーダーを実行するだけの場合は、モデルにどのフィールドを入力可能にするかを宣言する必要はありません(安全でない可能性があります)。

シードフォルダーには、DatabaseSeederクラスがあります。

class DatabaseSeeder extends Seeder {

    /**
    * Run the database seeds.
    *
    * @return void
    */

    public function run()
    {
        Eloquent::unguard();

        //$this->call('UserTableSeeder');
    }
}

このクラスはファサードとして機能し、実行する必要のあるすべてのシーダーをリストします。php artisan db:seed --class="UsersTableSeeder"コマンドで行ったように、artisanを介してUsersTableSeederシーダーを手動で呼び出す場合、このDatabaseSeederクラスをバイパスします。

このDatabaseSeederクラスでは、コマンドをEloquent::unguard();使用してすべてのテーブルに一時的な一括割り当てを行うことができます。これは、データベースをシードするときに必要なことです。このunguardメソッドは、php aristan db:seedコマンドため、モデルでフィールドを入力可能にするのではなく、一時的なものです(承認された回答やその他の回答に記載されています)。

必要なことは$this->call('UsersTableSeeder');、DatabaseSeederクラスのrunメソッドにを追加して、php aristan db:seedデフォルトでDatabaseSeederを実行するCLIで実行することだけです。

また、Laravalは単数形のUserを使用しているのに対し、複数のクラス名のUserを使用していることに注意してください。クラスを従来の単数形に変更する場合//$this->call('UserTableSeeder');は、すでに割り当てられているが、デフォルトでDatabaseSeederクラスでコメント化されているをコメント解除できます。


4
偏執狂と純粋主義者のために:あなたはまた\Eloquent::reguard();、あなたの大量の割り当てが完了した後のために、を使用することに感謝を見つけるでしょう。
CenterOrbit

10

作成するには、すべてのフィールドが入力可能なだけで、あなたのクラスに宣言し、:

protected $guarded = array();

これにより、各フィールドを宣言せずにfillメソッドを呼び出すことができます。


7

Eloquent::unguard();シードを実行するときにrunメソッドの先頭に追加するだけで、シードする必要$fillableがあるすべてのモデルで配列を作成する必要はありません。

通常、これはDatabaseSeederクラスですでに指定されています。ただし、UsersTableSeeder直接呼び出すので:

php artisan db:seed --class="UsersTableSeeder"

Eloquent::unguard(); 呼び出されておらず、エラーが発生します。



1

このようにモデルを拡張すると、MassAssignmentExceptionが発生しました。

class Upload extends Eloquent {

}

私はこのような配列を挿入しようとしていました

Upload::create($array);//$array was data to insert.

アップロードモデルを作成したときに問題が解決されました

class Upload extends Eloquent {
    protected $guarded = array();  // Important
}

リファレンスhttps://github.com/aidkit/aidkit/issues/2#issuecomment-21055670


1

コントローラーファイル内のユーザーの適切なモデル。

<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\User;

0

データベースにテーブルとフィールドがある場合は、次のコマンドを使用できます。

php artisan db:seed --class=UsersTableSeeder --database=YOURDATABSE

0

データベースをシードする場合、これは良い方法ではありません。偽物を
使うハードコーディングの代わりにをます。これを行う前に、テーブルを切り捨てた方がよいでしょう。

この例を考えてみましょう:

    // Truncate table.  
    DB::table('users')->truncate();

    // Create an instance of faker.
    $faker = Faker::create();

    // define an array for fake data.
    $users = [];

    // Make an array of 500 users with faker.
    foreach (range(1, 500) as $index)
    {
        $users[] = [
            'group_id' => rand(1, 3),
            'name' => $faker->name,
            'company' => $faker->company,
            'email' => $faker->email,
            'phone' => $faker->phoneNumber,
            'address' => "{$faker->streetName} {$faker->postCode} {$faker->city}",
            'about' => $faker->sentence($nbWords = 20, $variableNbWords = true),
            'created_at' => new DateTime,
            'updated_at' => new DateTime,
        ];
    }

    // Insert into database.
    DB::table('users')->insert($users);

0

使用する充填可能なのアレイを使用してフィールドを埋めることができたlaravelを伝えるために。デフォルトでは、Laravelは配列を介したデータベースフィールドの更新を許可していません

Protected $fillable=array('Fields you want to fill using array');

fillableの反対はガード可能です。


-1

挿入のOOPメソッドを使用する場合は、大量のアクション/入力可能なプロパティについて心配する必要はありません。

$user = new User;
$user->username = 'Stevo';
$user->email = 'steve@rute.co.za';
$user->password = '45678';
$user->save();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.