MassAssignmentException en Laravel

5 minutos de lectura

Soy un novato de Laravel. Quiero sembrar mi base de datos. Cuando ejecuto el comando seed 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' => 'psheer@rute.co.za',
                'password' => '45678'
            ]);

            User::create([
                'username' => 'Stevo',
                'email' => 'steve@rute.co.za',
                'password' => '45678'
            ]);
    }
}

avatar de usuario
Alejandro Butynski

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

Laravel proporciona por defecto 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 password o role. Podría generar un problema de seguridad porque los usuarios podrían actualizar los valores de estos campos cuando no lo deseen.

  • -1 Si bien esto funciona, la solución de Pascalculator es mejor, ya que desprotege solo cuando se necesita la asignación masiva y no durante la vida útil de la aplicación.

    – Emragins

    10 de octubre de 2014 a las 3:51

  • Tiene razón, en el contexto específico de la inicialización de bases de datos, debería ser mejor quitar la protección solo durante la inicialización. Pero, debido a que esta respuesta parece convertirse en un tema de referencia sobre MassAssignmentException y como cree que mi respuesta es una buena solución genérica, la mantendré como está.

    – Alejandro Butynski

    7 abr 2015 a las 10:27

  • Alexandre, me resulta difícil 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 funcionará, pero no cumple con la convención de Laravel.

    – Calculadora de Pas

    12 de abril de 2015 a las 11:41

  • 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 su solución puede ser tan buena como la mía, la voté y animo a otros a leerla 🙂

    – Alejandro Butynski

    14 de abril de 2015 a las 8:52

  • ‘contraseña’ => bcrypt(‘45678’)

    – Douglas.Sesar

    21 de agosto de 2015 a las 17:16

avatar de usuario
calculadora

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 una sembradora. Sin embargo, en mi opinión, no es necesario (y podría ser inseguro) declarar qué campos deben poder completarse en su modelo si solo necesita ejecutar una sembradora.

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 semillas que deben ejecutarse. Si llama a la sembradora UsersTableSeeder manualmente a través de artesano, como lo hizo con el php artisan db:seed --class="UsersTableSeeder" comando, omite esta clase DatabaseSeeder.

En esta clase DatabaseSeeder el comando Eloquent::unguard(); permite la asignación masiva temporal en todas las tablas, que es exactamente lo que necesita cuando está inicializando una base de datos. Este método de desprotección solo se ejecuta cuando ejecuta el php aristan db:seed comando, por lo tanto, 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'); al método de ejecución en la clase DatabaseSeeder y ejecute php aristan db:seed en su CLI que por defecto ejecutará DatabaseSeeder.

También tenga en cuenta que está utilizando un nombre de clase plural Usuarios, mientras que Laraval usa la forma singular Usuario. Si decide cambiar su clase a la forma singular convencional, simplemente puede descomentar el //$this->call('UserTableSeeder'); que ya ha sido asignado pero comentado por defecto en la clase DatabaseSeeder.

  • Para los paranoicos y los puristas: también apreciarán el uso \Eloquent::reguard();para después de completar sus asignaciones masivas.

    – Órbita central

    2 jun 2015 a las 20:53


Para hacer todos los campos rellenablessolo declara en tu clase:

protected $guarded = array();

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

  • No quiero usar un campo específico en la matriz. ¿Qué tengo que hacer?

    -Pramod Amrutkar

    13 dic 2021 a las 13:40


Solo agrega Eloquent::unguard(); en la parte superior del método de ejecución cuando haces una semilla, no es necesario crear un $fillable matriz en todos los modelos que tiene que sembrar.

Normalmente esto ya está especificado en el DatabaseSeeder clase. Sin embargo, debido a que está llamando al UsersTableSeeder directamente:

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

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

Usé esto y no tengo ningún problema:

protected $guarded=[];

avatar de usuario
Amit Garg

Obtuve 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 ha sido resuelto cuando creé Subir modelo como

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

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

avatar de usuario
Raúl Hirve

Modelo propio del usuario en su archivo de controlador.

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

¿Ha sido útil esta solución?