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

คำตอบ:


231

อ่านส่วนนี้ของ Laravel doc: 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และเนื่องจากคิดว่าคำตอบของฉันเป็นคำตอบทั่วไปที่ดีฉันจะเก็บไว้ตามที่เป็นอยู่
Alexandre Butynski

อาเล็กฉันพบว่ามันยากที่จะทำตามตรรกะของคุณ หากคุณเห็นด้วยคุณอาจเปลี่ยนคำตอบของคุณเองได้เช่นกันเพราะมันกำลังกลายเป็นหัวข้ออ้างอิง คำตอบที่คุณแนะนำจะใช้ได้จริง แต่ไม่เป็นไปตามอนุสัญญา Laravel
Pascalculator

4
ฉันเก็บคำตอบไว้เหมือนเดิมเพราะฉันคิดว่ามันเป็นรูปแบบทั่วไปที่ดี (ฉันใช้ในโครงการของฉัน) และเพราะฉันคิดว่ามันไม่สอดคล้องกับอนุสัญญา Laravel มากกว่าคำตอบของคุณ (ดูเอกสาร) แต่เนื่องจากความคิดเห็นส่วนใหญ่เป็นเรื่องที่ดีและเนื่องจากวิธีการแก้ปัญหาของคุณดีพอ ๆ กับของฉันฉันจึงโหวตและแนะนำให้คนอื่นอ่าน :)
Alexandre Butynski

'รหัสผ่าน' => bcrypt ( '45678')
Douglas.Sesar

31

ฉันใช้ Laravel 4.2

ข้อผิดพลาดที่คุณเห็น

[Illuminate\Database\Eloquent\MassAssignmentException]
username

แน่นอนว่าเป็นเพราะฐานข้อมูลได้รับการปกป้องจากการกรอกข้อมูลซึ่งเป็นสิ่งที่คุณกำลังทำเมื่อคุณดำเนินการกับ seeder อย่างไรก็ตามในความคิดของฉันไม่จำเป็น (และอาจไม่ปลอดภัย) ที่จะประกาศว่าช่องใดที่ควรกรอกในแบบจำลองของคุณหากคุณต้องการเพียงแค่เรียกใช้ seeder เท่านั้น

ในโฟลเดอร์ seeding ของคุณคุณมีคลาส DatabaseSeeder:

class DatabaseSeeder extends Seeder {

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

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

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

คลาสนี้ทำหน้าที่เป็นส่วนหน้าแสดงรายชื่อผู้เริ่มต้นทั้งหมดที่จำเป็นต้องดำเนินการ หากคุณเรียกใช้ UsersTableSeeder seeder ด้วยตนเองผ่านช่างฝีมือเช่นเดียวกับที่คุณทำกับ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

โปรดทราบว่าคุณกำลังใช้ผู้ใช้ชื่อคลาสพหูพจน์ในขณะที่ Laraval ใช้รูปแบบเอกพจน์ User หากคุณตัดสินใจที่จะเปลี่ยนคลาสของคุณเป็นรูปแบบเอกพจน์ธรรมดาคุณสามารถยกเลิกการใส่ความคิดเห็น//$this->call('UserTableSeeder');ที่ได้รับมอบหมายไปแล้ว แต่แสดงความคิดเห็นตามค่าเริ่มต้นในคลาส DatabaseSeeder


4
สำหรับผู้หวาดระแวงและคนเจ้าระเบียบ: คุณจะพบความซาบซึ้งในการใช้\Eloquent::reguard();งานเพราะหลังจากการมอบหมายงานมวลชนของคุณเสร็จสมบูรณ์
CenterOrbit

10

ในการทำให้ทุกช่องกรอกข้อมูลได้เพียงแค่ประกาศในชั้นเรียนของคุณ:

protected $guarded = array();

สิ่งนี้จะช่วยให้คุณสามารถเรียกใช้วิธีการเติมโดยไม่ต้องประกาศแต่ละฟิลด์


7

เพียงเพิ่มEloquent::unguard();วิธีการรันด้านบนเมื่อคุณทำ seed ไม่จำเป็นต้องสร้าง$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/issues/2#issuecomment-21055670



0

หากคุณมีตารางและฟิลด์บนฐานข้อมูลคุณสามารถใช้คำสั่งนี้:

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

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 ไม่อนุญาตให้อัพเดตฟิลด์ฐานข้อมูลผ่านอาร์เรย์

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

ตรงข้ามfillableเป็นguardable


-1

หากคุณใช้วิธีการแทรก OOP คุณไม่จำเป็นต้องกังวลเกี่ยวกับคุณสมบัติมวลการกระทำ / การเติม:

$user = new User;
$user->username = 'Stevo';
$user->email = 'steve@rute.co.za';
$user->password = '45678';
$user->save();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.