MassAssignmentException у Ларавелі


108

Я новачок Laravel. Я хочу закласти свою базу даних. Коли я запускаю команду set, я отримую виняток

  [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: 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і тому, що вона вважає, що моя відповідь є хорошим загальним рішенням, я буду тримати її такою, якою є.
Олександр Бутинський

Олександре, мені важко слідувати вашій логіці. Якщо ви згодні, ви можете також змінити власну відповідь, тим більше, що вона стає довідковою темою. Відповідь, яку ви запропонували, дійсно спрацює, але не відповідає конвенції Ларавеля.
Pascalculator

4
Я дотримуюся своєї відповіді так, тому що я вважаю, що це хороша загальна модель (я використовую її у своїх проектах) і тому, що я вважаю, що це не більше чи менше відповідає конвенції Ларавеля, ніж ваша відповідь (див. Документ). Але оскільки множина думок велика і тому що ваше рішення може бути таким же хорошим, як і моє, я підтримав його і закликаю інших прочитати його :)
Олександр Бутинський,

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

Цей клас виступає фасадом, перелічуючи всі сівалки, які потрібно виконати. Якщо ви зателефонуєте на сівальник UsersTableSeeder вручну через ремісник, як це було зроблено з php artisan db:seed --class="UsersTableSeeder"командою, ви обійдете цей клас DatabaseSeeder.

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

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

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


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

10

Щоб заповнити всі поля заповненими , просто заявіть про свій клас:

protected $guarded = array();

Це дасть змогу викликати метод заповнення без оголошення кожного поля.


7

Просто додайте Eloquent::unguard();у верхній частині методу запуску, коли ви робите насіння, не потрібно створювати $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/isissue/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

Якщо ви використовуєте метод вставки OOP, вам не потрібно турбуватися про властивості масової дії / заповнення:

$user = new User;
$user->username = 'Stevo';
$user->email = 'steve@rute.co.za';
$user->password = '45678';
$user->save();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.