Laravel'de MassAssignmentException


108

Ben bir Laravel acemisiyim. Veritabanımı başlatmak istiyorum. Tohum komutunu çalıştırdığımda bir istisna alıyorum

  [Illuminate\Database\Eloquent\MassAssignmentException]
  username



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

Neyi yanlış yapıyorum. Kullandığım komut:

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

Benim tohum sınıfım aşağıdaki gibidir:

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

Yanıtlar:


231

Laravel belgesinin bu bölümünü okuyun: http://laravel.com/docs/eloquent#mass-assignment

Laravel, toplu atama güvenlik sorunlarına karşı varsayılan olarak bir koruma sağlar. Bu nedenle, hangi alanların "toplu olarak atanabileceğini" manuel olarak tanımlamanız gerekir:

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

Uyarı:password veya gibi kritik alanların toplu olarak atanmasına izin verirken dikkatli olun role. Kullanıcılar istemediğinizde bu alanların değerlerini güncelleyebileceklerinden bir güvenlik sorununa yol açabilir.


7
-1 Bu işe yararken, Pascalculator'ın çözümü, uygulamanın ömrü boyunca değil, yalnızca toplu atama gerektiğinde korumayı kaldırması açısından daha iyidir.
2014

1
Haklısın, belirli veritabanı tohumlama bağlamında, yalnızca tohumlama sırasında korumayı kaldırmak daha iyi olacaktır. Ancak, bu cevap bir referans konusu haline geldiğinden MassAssignmentExceptionve cevabımın iyi bir genel çözüm olduğunu düşündüğü için olduğu gibi tutacağım.
Alexandre Butynski

Alexandre, mantığını takip etmekte zorlanıyorum. Kabul ediyorsanız, kendi cevabınızı değiştirebilirsiniz, daha da çok, çünkü bu bir referans konusu haline geliyor. Önerdiğiniz cevap gerçekten işe yarayacak, ancak Laravel sözleşmesine uygun değil.
Pascalculator

4
Cevabımı olduğu gibi tutuyorum çünkü bunun iyi bir genel model olduğunu düşünüyorum (bunu projelerimde kullanıyorum) ve Laravel sözleşmesine sizin cevabınızdan daha fazla veya daha az uygun olmadığını düşünüyorum (belgeye bakın). Ancak, fikirlerin çokluğu harika olduğu ve çözümünüz benimki kadar iyi olabileceği için, onu destekledim ve başkalarını da okumaya teşvik ediyorum :)
Alexandre Butynski 14'15'te

'password' => bcrypt ('45678')
Douglas.Sesar

31

Laravel 4.2 kullanıyorum.

gördüğün hata

[Illuminate\Database\Eloquent\MassAssignmentException]
username

gerçekten de veritabanı toplu olarak doldurulmaktan korunmaktadır, bu da bir tohumlayıcıyı çalıştırırken yaptığınız şeydir. Ancak, bence, yalnızca bir tohumlayıcı çalıştırmanız gerekiyorsa, modelinizde hangi alanların doldurulabileceğini belirtmek gerekli değildir (ve güvensiz olabilir).

Tohumlama klasörünüzde DatabaseSeeder sınıfınız var:

class DatabaseSeeder extends Seeder {

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

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

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

Bu sınıf, uygulanması gereken tüm ekme makinelerini listeleyen bir cephe görevi görür. UsersTableSeeder tohumlayıcıyı, php artisan db:seed --class="UsersTableSeeder"komutta yaptığınız gibi, artisan aracılığıyla manuel olarak çağırırsanız, bu DatabaseSeeder sınıfını atlarsınız .

Bu DatabaseSeeder sınıfında komut Eloquent::unguard();, tüm tablolarda geçici toplu atamaya izin verir; bu, bir veritabanını tohumlarken tam olarak ihtiyacınız olan şeydir. Bu korumasız yöntem, yalnızcaphp aristan db:seed komutu , bu nedenle modelinizdeki alanları doldurulabilir hale getirmenin aksine geçicidir (kabul edilen ve diğer yanıtlarda belirtildiği gibi).

Tüm yapmanız gereken $this->call('UsersTableSeeder');, DatabaseSeeder sınıfındaki run yöntemini eklemek ve php aristan db:seedvarsayılan olarak DatabaseSeeder'ı çalıştıracak olan CLI'nizde çalıştırmaktır.

Ayrıca , Laraval tekil form User'ı kullanırken, Users sınıfının çoğul bir adını kullandığınızı unutmayın. Sınıfınızı geleneksel tekil biçime değiştirmeye karar verirseniz //$this->call('UserTableSeeder');, DatabaseSeeder sınıfında önceden atanmış ancak varsayılan olarak yorumlanmış olanın açıklamasını kaldırabilirsiniz .


4
Paranoyak ve saf olanlar için: \Eloquent::reguard();Kitle Görevleriniz tamamlandıktan sonra, kullanımda da takdir göreceksiniz .
CenterOrbit

10

Tüm alanları doldurulabilir hale getirmek için, sınıfınızda şunları beyan etmeniz yeterlidir:

protected $guarded = array();

Bu, her alanı bildirmeden doldurma yöntemini çağırmanızı sağlayacaktır.


7

Eloquent::unguard();Bir tohum oluşturduğunuzda çalıştırma yönteminin en üstüne ekleyin , tohumlamanız gereken $fillabletüm modellerde bir dizi oluşturmanıza gerek yoktur .

Normalde bu, DatabaseSeedersınıfta zaten belirtilmiştir . Ancak UsersTableSeederdoğrudan aradığınız için :

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

Eloquent::unguard(); aranmıyor ve hata veriyor.



1

Modelimi bu şekilde genişlettiğimde MassAssignmentException alıyordum.

class Upload extends Eloquent {

}

Böyle bir dizi eklemeye çalışıyordum

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

Sayı olmuştur azmini vardır Ben Yükle Model yarattı

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

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


1

Denetleyici dosyanızda kullanıcıya uygun model.

<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\User;

0

Veritabanında tablo ve alanlarınız varsa, bu komutu basitçe kullanabilirsiniz:

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

0

Veritabanını tohumlamak istediğinizde bu iyi bir yol değildir.
Kullanım sahtekar yerine sert kodlama ve tüm bu belki trankulatı tabloları daha iyidir önce.

Şu örneği düşünün:

    // 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

Kullanım fillable bir dizi kullanarak alanlar doldurulabilir hangi laravel anlatmak için. Laravel varsayılan olarak veritabanı alanlarının bir dizi aracılığıyla güncellenmesine izin vermez

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

Karşıt doldurulabilen bir guardable .


-1

OOP ekleme yöntemini kullanırsanız, toplu hareket / doldurulabilir özellikler hakkında endişelenmenize gerek yoktur:

$user = new User;
$user->username = 'Stevo';
$user->email = 'steve@rute.co.za';
$user->password = '45678';
$user->save();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.