This mass assignment error is a really common one when working with Laravel. Here's how to fix the inability to insert/update records.
Mass assignment in Laravel Eloquent allows you to quickly insert or update multiple fields in a database table at once instead of setting them one by one, like this:
User::create([
'name' => 'Alex',
'email' => 'alex@codecourse.com',
'password' => bcrypt('password'),
]);
By default, Laravel protects against mass assignment to prevent security issues (e.g., accidentally allowing users to change fields they shouldn’t). If you try the above without defining fillable fields, you’ll get the "Add [column] to fillable property to allow mass assignment on [Model]" error.
Let's stick with the example of creating a user and imagine we've added an additional column, username.
When we want to insert/update columns on models, we have to either add the column name to the $fillable
property array on the model, or create this property if we're starting a model from scratch.
By default, your User
model in Laravel will likely look like this:
class User extends Authenticatable
{
/** @use HasFactory<\Database\Factories\UserFactory> */
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var list<string>
*/
protected $fillable = [
'name',
'email',
'password',
];
// ...
}
So, taking the example of adding an additional username column that we need to fill, we'd update $fillable
like this:
class User extends Authenticatable
{
/** @use HasFactory<\Database\Factories\UserFactory> */
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var list<string>
*/
protected $fillable = [
'name',
'email',
'password',
'username'
];
// ...
}
Generally, adding a $fillable
property to your models isn't always necessary, and many developers will choose to simply unguard everything. There are a couple of ways to do this.
Let's imagine we have a new model called Article
(like what you're viewing now).
You can skip $fillable
and instead set $guarded
to false
:
class Article extends Model
{
protected $guarded = false;
}
Or, you can choose to guard only the ID:
class Article extends Model
{
protected $guarded = ['id'];
}
Or, if you prefer a global approach, you can unguard everything, perhaps within AppServiceProvider
:
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Model::unguard();
}
}
This will unguard all Eloquent models by default.
Mass assignment is there to protect you against columns you don't want to be filled.
You should be doing this either way, but particularly if you're unguarding your models, you want to ensure you're carefully restricting data being used to create/update models.
Here's an example of what not to do:
class ArticleController extends Controller
{
public function store(Request $request)
{
// Validate here
Article::create($request->all());
}
}
By using $request->all()
, you're allowing anything to potentially be used to construct a model. That's what mass assignment protects you from!
Instead, it's best to do this:
class ArticleController extends Controller
{
public function store(Request $request)
{
// Validate here
Article::create($request->only('title', 'teaser', 'body'));
}
}
By using only
, you specify what data can be used to construct the article.
If you come across the "Add [column] to fillable property to allow mass assignment on [Model]" error in Laravel, you have a few options:
$fillable
property of a model$guarded
property to false
in your modelThere's nothing wrong with unguarding everything. A lot of Laravel developers do this by default. As long as you're not allowing data to be passed into your model creation directly, you won't have any issues with mass assignment.