MassAssignmentException en Laravel

108

Soy un novato en Laravel. Quiero sembrar mi base de datos. Cuando ejecuto el comando semilla, obtengo una excepción

  [Illuminate\Database\Eloquent\MassAssignmentException]
  username



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

Qué estoy haciendo mal. El comando que uso es:

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

Mi clase semilla es la siguiente:

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

Respuestas:

231

Lea esta sección del documento de Laravel: http://laravel.com/docs/eloquent#mass-assignment

Laravel proporciona de forma predeterminada una protección contra problemas de seguridad de asignación masiva. Es por eso que debe definir manualmente qué campos podrían ser "asignados en masa":

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

Advertencia: tenga cuidado cuando permita la asignación masiva de campos críticos como passwordo role. Podría provocar un problema de seguridad porque los usuarios podrían actualizar los valores de este campo cuando no lo deseen.

Alexandre Butynski
fuente
7
-1 Si bien esto funciona, la solución de Pascalculator es mejor ya que solo desprotege cuando se necesita la asignación masiva y no durante la vida útil de la aplicación.
emragins
1
Tiene razón, en el contexto específico de la inicialización de la base de datos, debería ser mejor desproteger solo durante la inicialización. Pero, debido a que esta respuesta parece convertirse en un tema de referencia MassAssignmentExceptiony porque cree que mi respuesta es una buena solución genérica, la mantendré como está.
Alexandre Butynski
Alexandre, me cuesta seguir tu lógica. Si está de acuerdo, también podría cambiar su propia respuesta, más aún porque se está convirtiendo en un tema de referencia. La respuesta que ha sugerido realmente funcionará, pero no cumple con la convención de Laravel.
Pascalculator
4
Mantengo mi respuesta como está porque creo que es un buen patrón general (lo uso en mis proyectos) y porque creo que no cumple más o menos con la convención de Laravel que su respuesta (ver el documento). Pero, debido a que la pluralidad de opiniones es excelente y debido a que su solución puede ser tan buena como la mía, la voté a favor y animo a otros a leerla :)
Alexandre Butynski
'contraseña' => bcrypt ('45678')
Douglas.Sesar
31

Estoy usando Laravel 4.2.

el error que estas viendo

[Illuminate\Database\Eloquent\MassAssignmentException]
username

de hecho, se debe a que la base de datos está protegida contra el llenado en masa, que es lo que está haciendo cuando está ejecutando un sembrador. Sin embargo, en mi opinión, no es necesario (y podría ser inseguro) declarar qué campos deben ser rellenables en su modelo si solo necesita ejecutar un sembrador.

En su carpeta de inicialización tiene la clase DatabaseSeeder:

class DatabaseSeeder extends Seeder {

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

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

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

Esta clase actúa como una fachada, enumerando todas las sembradoras que deben ejecutarse. Si llama al sembrador UsersTableSeeder manualmente a través de artisan, como hizo con el php artisan db:seed --class="UsersTableSeeder"comando, omite esta clase DatabaseSeeder.

En esta clase de DatabaseSeeder, el comando Eloquent::unguard();permite la asignación masiva temporal en todas las tablas, que es exactamente lo que necesita cuando está sembrando una base de datos. Este método de desprotección solo se ejecuta cuando ejecuta el php aristan db:seedcomando, por lo que es temporal en lugar de hacer que los campos se puedan completar en su modelo (como se indica en las respuestas aceptadas y otras).

Todo lo que necesita hacer es agregar el $this->call('UsersTableSeeder');método de ejecución en la clase DatabaseSeeder y ejecutarlo php aristan db:seeden su CLI, que de forma predeterminada ejecutará DatabaseSeeder.

También tenga en cuenta que está usando un nombre de clase plural Users, mientras que Laraval usa la forma singular User. Si decide cambiar su clase a la forma singular convencional, simplemente puede descomentar la //$this->call('UserTableSeeder');que ya ha sido asignada pero comentada de forma predeterminada en la clase DatabaseSeeder.

Pascalculadora
fuente
4
Para los paranoicos y puristas: también encontrará apreciación en el uso \Eloquent::reguard();, para después de que se completen sus asignaciones masivas.
CenterOrbit
10

Para que todos los campos se puedan completar , simplemente declare en su clase:

protected $guarded = array();

Esto le permitirá llamar al método de relleno sin declarar cada campo.

Tiago Gouvêa
fuente
7

Simplemente agregue Eloquent::unguard();la parte superior del método de ejecución cuando realice una semilla, no es necesario crear una $fillablematriz en todos los modelos que tiene que sembrar.

Normalmente esto ya está especificado en la DatabaseSeederclase. Sin embargo, debido a que está llamando UsersTableSeederdirectamente a:

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

Eloquent::unguard(); no está siendo llamado y da el error.

bicicleta
fuente
4

Usé esto y no tengo ningún problema:

protected $guarded=[];
parastoo amini
fuente
1

Recibí MassAssignmentException cuando extendí mi modelo de esta manera.

class Upload extends Eloquent {

}

Estaba tratando de insertar una matriz como esta

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

El problema se resolvió cuando creé Cargar modelo como

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

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

Amit Garg
fuente
1

Modelo adecuado de usuario en su archivo de controlador.

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

si tiene una tabla y campos en la base de datos, simplemente puede usar este comando:

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

Esta no es una buena forma cuando desea sembrar una base de datos.
Use faker en lugar de codificación rígida, y antes de todo esto, tal vez sea mejor truncar las tablas.

Considere este ejemplo:

    // 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);
Amín
fuente
0

Use el rellenable para decirle a laravel qué campos se pueden completar usando una matriz. De forma predeterminada, Laravel no permite que los campos de la base de datos se actualicen a través de una matriz

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

Lo contrario de rellenable es vigilable .

Sameer Shaikh
fuente
-1

Si usa el método de inserción OOP, no necesita preocuparse por las propiedades de acción masiva / rellenables:

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