MassAssignmentException в Laravel

74

Я новичок в Laravel. Я хочу засеять мою базу данных. Когда я запускаю команду seed, я получаю исключение

  [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' => '[email protected]',
                'password' => '45678'
            ]);

            User::create([
                'username' => 'Stevo',
                'email' => '[email protected]',
                'password' => '45678'
            ]);
    }
}
Теги:

11 ответов

185
Лучший ответ

Прочтите этот раздел документа Laravel: http://laravel.com/docs/eloquent#mass-assignment

Laravel предоставляет по умолчанию защиту от проблем безопасности массового присвоения. Поэтому вам нужно вручную определить, какие поля могут быть "назначены массой":

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

Предупреждение: будьте осторожны, если разрешите массовое присвоение критических полей, например password или role. Это может привести к проблеме безопасности, поскольку пользователи могут обновлять эти значения полей, если вы этого не хотите.

  • 7
    -1 Хотя это работает, решение от Pascalculator лучше в том, что оно не защищает только тогда, когда необходимо массовое назначение, а не на весь срок службы приложения.
  • 1
    Вы правы, в конкретном контексте заполнения базы данных лучше не охранять только во время заполнения. Но, поскольку этот ответ, по-видимому, становится справочной темой о MassAssignmentException и поскольку он считает мой ответ хорошим обобщенным решением, я MassAssignmentException его как есть.
Показать ещё 8 комментариев
24

Я использую 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');
    }
}

Этот класс действует как фасад, перечисляя все сеялки, которые необходимо выполнить. Если вы вызываете сеялку UsersTableSeeder вручную с помощью мастера, как и в команде php artisan db:seed --class="UsersTableSeeder", вы обходите этот класс DatabaseSeeder.

В этом классе DatabaseSeeder команда Eloquent::unguard(); разрешает временное массовое присвоение во всех таблицах, что именно то, что вам нужно при посеве базы данных. Этот метод unguard выполняется только при запуске команды php aristan db:seed, поэтому он является временным, а не делает поля заполняемыми в вашей модели (как указано в принятых и других ответах).

Все, что вам нужно сделать, это добавить $this->call('UsersTableSeeder'); к методу запуска в классе DatabaseSeeder и запустить php aristan db:seed в вашем CLI, который по умолчанию будет выполнять DatabaseSeeder.

Также обратите внимание на, что вы используете множественное имя класса Users, в то время как Laraval использует единственную форму User. Если вы решили изменить свой класс на обычную единую форму, вы можете просто раскомментировать //$this->call('UserTableSeeder');, который уже был назначен, но закомментирован по умолчанию в классе DatabaseSeeder.

  • 3
    Для параноиков и пуристов: вы также найдете высокую оценку в использовании \Eloquent::reguard(); , после того, как ваши массовые задания завершены.
7

Просто добавьте Eloquent::unguard(); в начало метода запуска, когда вы делаете семя, не нужно создавать массив $fillable во всех моделях, которые вы должны засеять.

Обычно это уже указано в классе DatabaseSeeder. Однако, поскольку вы вызываете UsersTableSeeder напрямую:

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

Eloquent::unguard(); не вызывается и дает ошибку.

4

Чтобы сделать все поля заполняемыми, просто объявите в своем классе:

protected $guarded = array();

Это позволит вам вызвать метод заполнения без объявления каждого поля.

1

Пользовательская модель в файле вашего контроллера.

<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\User;
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

0

Я использовал это и не имею проблем:

protected $guarded=[];
0

Это нехорошо, когда вы хотите посеять базу данных.
Используйте 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);
0

Используйте fillable, чтобы сообщить laravel, какие поля могут быть заполнены с помощью массива. По умолчанию laravel не позволяет обновлять поля базы данных через массив

Защищенный $fillable = array ('Поля, которые вы хотите заполнить с помощью массива');

Противоположность fillable является защищенной.

0

Если у вас есть таблица и поля в базе данных, вы можете просто использовать эту команду:

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

Если вы используете метод ввода ООП, вам не нужно беспокоиться о свойствах массового действия/заполнения:

$user = new User;
$user->username = 'Stevo';
$user->email = '[email protected]';
$user->password = '45678';
$user->save();

Ещё вопросы

Сообщество Overcoder
Наверх
Меню