MassAssignmentException в Laravel

108

Я новичок в 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' => 'psheer@rute.co.za',
                'password' => '45678'
            ]);

            User::create([
                'username' => 'Stevo',
                'email' => 'steve@rute.co.za',
                'password' => '45678'
            ]);
    }
}
user1801060
источник

Ответы:

231

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

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

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

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

Александр Бутынский
источник
7
-1 Хотя это работает, решение от Pascalculator лучше в том, что оно снимает охрану только тогда, когда требуется массовое присвоение, а не на время жизни приложения.
emragins
1
Вы правы, в конкретном контексте раздачи базы данных лучше отключать только во время раздачи. Но поскольку этот ответ, кажется, стал справочной темой MassAssignmentExceptionи поскольку он считает, что мой ответ является хорошим общим решением, я оставлю его как есть.
Александр Бутынски
Александр, мне трудно следовать твоей логике. Если вы согласны, вы можете изменить свой собственный ответ, тем более что он становится справочной темой. Предложенный вами ответ действительно будет работать, но он не соответствует соглашению Laravel.
Паскалькулятор
4
Я сохраняю свой ответ как есть, потому что считаю это хорошим общим шаблоном (я использую его в своих проектах) и потому, что я думаю, что он не более или менее соответствует соглашению Laravel, чем ваш ответ (см. Документ). Но поскольку множество мнений велико и ваше решение может быть таким же хорошим, как и мое, я проголосовал за него и призываю других прочитать его :)
Александр Бутынски
'password' => bcrypt ('45678')
Дуглас, Сезар,
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');
    }
}

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

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

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

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

Pascalculator
источник
4
Для параноиков и пуристов: вы также найдете признательность в использовании \Eloquent::reguard();после того, как ваши массовые задания будут выполнены.
CenterOrbit
10

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

protected $guarded = array();

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

Тьяго Гувеа
источник
7

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

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

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

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

велосипед
источник
4

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

protected $guarded=[];
парастоо амини
источник
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

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

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

Противоположность заполняемых является guardable .

Самир Шейх
источник
-1

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

$user = new User;
$user->username = 'Stevo';
$user->email = 'steve@rute.co.za';
$user->password = '45678';
$user->save();
Марк Шуст из M.academy
источник