【问题标题】:MassAssignmentException in LaravelLaravel 中的 MassAssignmentException
【发布时间】:2014-04-12 08:58:21
【问题描述】:

我是 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'
            ]);
    }
}

【问题讨论】:

    标签: php laravel


    【解决方案1】:

    使用 fillable 告诉 laravel 哪些字段可以使用数组填充。 默认情况下,Laravel 不允许通过数组更新数据库字段

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

    fillable的反义词是guardable

    【讨论】:

      【解决方案2】:

      在您的控制器文件中使用正确的模型。

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

      【讨论】:

        【解决方案3】:

        我用过这个没问题:

        protected $guarded=[];
        

        【讨论】:

          【解决方案4】:

          当您想播种数据库时,这不是一个好方法。
          使用faker 而不是硬编码,在这之前最好截断表。

          考虑这个例子:

              // 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);
          

          【讨论】:

            【解决方案5】:

            阅读这部分 Laravel 文档:http://laravel.com/docs/eloquent#mass-assignment

            Laravel 默认提供针对批量分配安全问题的保护。这就是为什么您必须手动定义哪些字段可以“批量分配”:

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

            警告:当您允许像 passwordrole 这样的关键字段的批量分配时要小心。这可能会导致安全问题,因为用户可以在您不想更新时更新此字段值。

            【讨论】:

            • -1 虽然这可行,但 Pascalculator 的解决方案更好,因为它仅在需要批量分配时才解除保护,而不是在应用程序的生命周期内解除保护。
            • 你说得对,在数据库做种的具体情况下,最好只在做种的时候不防。但是,因为这个答案似乎成为关于MassAssignmentException 的参考主题,并且因为它认为我的答案是一个很好的通用解决方案,所以我会保持原样。
            • Alexandre,我发现很难遵循您的逻辑。如果您同意,您不妨更改自己的答案,更是如此,因为它正在成为一个参考主题。您建议的答案确实有效,但不符合 Laravel 约定。
            • 我保留我的答案是因为我认为这是一个很好的通用模式(我在我的项目中使用它)并且因为我认为它与你的答案相比并不或多或少地符合 Laravel 约定(见文档)。但是,因为多种意见很好,而且你的解决方案和我的一样好,所以我赞成它并鼓励其他人阅读它:)
            • '密码' => bcrypt('45678')
            【解决方案6】:

            如果使用 OOP 方式插入,则无需担心 mass-action/fillable 属性:

            $user = new User;
            $user->username = 'Stevo';
            $user->email = 'steve@rute.co.za';
            $user->password = '45678';
            $user->save();
            

            【讨论】:

              【解决方案7】:

              要使所有字段都可填写,只需在您的类上声明:

              protected $guarded = array();
              

              这将使您能够在不声明每个字段的情况下调用填充方法。

              【讨论】:

              • 我不想使用数组中的特定字段。我该怎么办?
              【解决方案8】:

              做种子时只需在run方法的顶部添加Eloquent::unguard();,无需在所有需要种子的模型中创建$fillable数组。

              通常这已经在DatabaseSeeder 类中指定。但是因为您直接调用UsersTableSeeder

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

              Eloquent::unguard(); 未被调用并给出错误。

              【讨论】:

                【解决方案9】:

                我正在使用 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');
                    }
                }
                

                这个类作为一个门面,列出所有需要执行的种子。如果您通过 artisan 手动调用 UsersTableSeeder 播种器,就像您使用 php artisan db:seed --class="UsersTableSeeder" 命令所做的那样,您将绕过此 DatabaseSeeder 类。

                在此 DatabaseSeeder 类中,命令 Eloquent::unguard(); 允许对所有表进行临时批量分配,这正是您在为数据库播种时所需要的。此 unguard 方法仅在您运行 php aristan db:seed 命令时执行,因此它是临时的,而不是使您的模型中的字段可填写(如接受和其他答案中所述)。

                您需要做的就是将$this-&gt;call('UsersTableSeeder'); 添加到DatabaseSeeder 类的run 方法中,然后在您的CLI 中运行php aristan db:seed,默认情况下会执行DatabaseSeeder。

                另请注意,您使用的是复数类名 Users,而 Laraval 使用单数形式 User。如果您决定将您的类更改为传统的单数形式,您可以简单地取消注释 //$this-&gt;call('UserTableSeeder');,它已经被分配,但在 DatabaseSeeder 类中默认被注释掉。

                【讨论】:

                • 对于偏执狂和纯粹主义者:在完成批量作业后,您还会发现使用\Eloquent::reguard(); 会很感激。
                【解决方案10】:

                当我像这样扩展我的模型时,我得到了 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

                【讨论】:

                  【解决方案11】:

                  如果你在数据库中有表和字段,你可以简单地使用这个命令:

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

                  【讨论】:

                    猜你喜欢
                    • 2018-04-08
                    • 2017-04-14
                    • 2014-05-09
                    • 1970-01-01
                    • 2016-05-07
                    • 2018-05-09
                    • 1970-01-01
                    • 2016-03-21
                    • 2013-06-24
                    相关资源
                    最近更新 更多