MassAssignmentException di Laravel

108

Saya seorang pemula Laravel. Saya ingin melakukan seed database saya. Ketika saya menjalankan perintah seed, saya mendapatkan pengecualian

  [Illuminate\Database\Eloquent\MassAssignmentException]
  username



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

Apa yang saya lakukan salah. Perintah yang saya gunakan adalah:

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

Kelas benih saya adalah sebagai berikut:

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

Jawaban:

231

Baca bagian ini dari dokumen Laravel: http://laravel.com/docs/eloquent#mass-assignment

Laravel secara default menyediakan perlindungan terhadap masalah keamanan penugasan massal. Itulah mengapa Anda harus secara manual menentukan bidang mana yang dapat "ditetapkan secara massal":

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

Peringatan: berhati-hatilah saat Anda mengizinkan penugasan massal bidang kritis seperti passwordatau role. Ini dapat menyebabkan masalah keamanan karena pengguna dapat memperbarui nilai bidang ini saat Anda tidak menginginkannya.

Alexandre Butynski
sumber
7
-1 Sementara ini berfungsi, solusi dari Pascalculator lebih baik karena melepaskan pelindung hanya ketika penugasan massal diperlukan dan bukan selama masa pakai aplikasi.
emragins
1
Anda benar, dalam konteks spesifik penyemaian database, sebaiknya lindungi hanya selama penyemaian. Tetapi, karena jawaban ini sepertinya menjadi topik referensi tentang MassAssignmentExceptiondan karena menurutnya jawaban saya adalah solusi umum yang baik, saya akan menyimpannya apa adanya.
Alexandre Butynski
Alexandre, menurutku sulit untuk mengikuti logika kamu. Jika Anda setuju, Anda mungkin juga mengubah jawaban Anda sendiri, terlebih lagi karena itu menjadi topik referensi. Jawaban yang Anda sarankan memang akan berhasil, tetapi tidak sesuai dengan konvensi Laravel.
Pascalculator
4
Saya menyimpan jawaban saya apa adanya karena menurut saya itu pola umum yang baik (saya menggunakannya dalam proyek saya) dan karena saya pikir itu tidak lebih atau kurang sesuai dengan konvensi Laravel daripada jawaban Anda (lihat dokumen). Tetapi, karena pluralitas opini itu bagus dan karena solusi Anda bisa sebaik solusi saya, saya memberikan suara positif dan mendorong orang lain untuk membacanya :)
Alexandre Butynski
'password' => bcrypt ('45678')
Douglas.Sesar
31

Saya menggunakan Laravel 4.2.

kesalahan yang Anda lihat

[Illuminate\Database\Eloquent\MassAssignmentException]
username

memang karena database dilindungi dari pengisian secara massal, itulah yang Anda lakukan saat menjalankan seeder. Namun, menurut pendapat saya, tidak perlu (dan mungkin tidak aman) untuk mendeklarasikan bidang mana yang harus dapat diisi dalam model Anda jika Anda hanya perlu menjalankan seeder.

Di folder seeding, Anda memiliki kelas DatabaseSeeder:

class DatabaseSeeder extends Seeder {

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

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

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

Kelas ini bertindak sebagai fasad, mendaftar semua seeder yang perlu dieksekusi. Jika Anda memanggil seeder UsersTableSeeder secara manual melalui artisan, seperti yang Anda lakukan dengan php artisan db:seed --class="UsersTableSeeder"perintah, Anda melewati kelas DatabaseSeeder ini.

Di kelas DatabaseSeeder ini, perintah Eloquent::unguard();memungkinkan penugasan massal sementara di semua tabel, yang persis seperti yang Anda butuhkan saat melakukan seeding database. Metode lengah ini hanya dijalankan saat Anda menjalankan php aristan db:seedperintah, oleh karena itu bersifat sementara dibandingkan membuat bidang dapat diisi dalam model Anda (seperti yang dinyatakan dalam jawaban yang diterima dan jawaban lainnya).

Yang perlu Anda lakukan adalah menambahkan metode $this->call('UsersTableSeeder');ke run di kelas DatabaseSeeder dan menjalankannya php aristan db:seeddi CLI yang secara default akan menjalankan DatabaseSeeder.

Perhatikan juga bahwa Anda menggunakan nama kelas jamak Users, sedangkan Laraval menggunakan bentuk tunggal User. Jika Anda memutuskan untuk mengubah kelas Anda ke bentuk tunggal konvensional, Anda cukup menghapus komentar //$this->call('UserTableSeeder');yang telah ditetapkan tetapi memberi komentar secara default di kelas DatabaseSeeder.

Pascalculator
sumber
4
Untuk paranoid, dan purists: Anda juga akan menemukan apresiasi dalam menggunakan \Eloquent::reguard();, karena setelah Tugas Massa Anda selesai.
CenterOrbit
10

Untuk membuat semua bidang bisa diisi , cukup nyatakan di kelas Anda:

protected $guarded = array();

Ini akan memungkinkan Anda untuk memanggil metode pengisian tanpa mendeklarasikan setiap bidang.

Tiago Gouvêa
sumber
7

Cukup tambahkan Eloquent::unguard();di bagian atas metode run ketika Anda melakukan seed, tidak perlu membuat $fillablearray di semua model yang harus Anda seed.

Biasanya ini sudah ditentukan di DatabaseSeederkelas. Namun karena Anda menelepon UsersTableSeedersecara langsung:

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

Eloquent::unguard(); tidak dipanggil dan memberikan kesalahan.

sepeda
sumber
4

Saya menggunakan ini dan tidak punya masalah:

protected $guarded=[];
parastoo amini
sumber
1

Saya mendapatkan MassAssignmentException saat saya memperluas model saya seperti ini.

class Upload extends Eloquent {

}

Saya mencoba memasukkan array seperti ini

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

Masalah telah diatasi saat saya membuat Model Unggahan sebagai

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

Referensi https://github.com/aidkit/aidkit/issues/2#issuecomment-21055670

Amit Garg
sumber
1

Model yang sesuai pengguna di file pengontrol Anda.

<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\User;
Rahul Hirve
sumber
0

jika Anda memiliki tabel dan bidang di database Anda cukup menggunakan perintah ini:

php artisan db:seed --class=UsersTableSeeder --database=YOURDATABSE
DolDurma
sumber
0

Ini bukan cara yang baik saat Anda ingin melakukan seeding database.
Gunakan faker daripada hard coding, dan sebelum semua ini mungkin lebih baik untuk memotong tabel.

Pertimbangkan contoh ini:

    // 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);
Amin
sumber
0

Gunakan bisa diisi untuk memberitahu LARAVEL yang bidang dapat diisi menggunakan array. Secara default, Laravel tidak mengizinkan bidang database diperbarui melalui array

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

Kebalikan dari yang bisa diisi adalah guardable .

Sameer Shaikh
sumber
-1

Jika Anda menggunakan metode penyisipan OOP, Anda tidak perlu khawatir tentang properti aksi massa / yang dapat diisi:

$user = new User;
$user->username = 'Stevo';
$user->email = '[email protected]';
$user->password = '45678';
$user->save();
Mark Shust di M.academy
sumber