Another reason I like fillable instead of guarded

Every little bit helps

Joel Clermont
Joel Clermont
2024-02-07

Fillable versus guarded is one of the classic Laravel debates. We prefer to use fillable in our projects, and I'm not going to rehash all the reasons, but I am going to share an interesting one you may not be aware of.

Did you know that listing columns in guarded triggers an extra query when you create or update a model?

Here's the relevant code in the Laravel 10 source:

// Illuminate\Database\Eloquent\Concerns\GuardsAttributes.php
protected function isGuardableColumn($key)
{
    if (! isset(static::$guardableColumns[get_class($this)])) {
        $columns = $this->getConnection() // <-- here's the extra query
                    ->getSchemaBuilder()
                    ->getColumnListing($this->getTable());

        if (empty($columns)) {
            return true;
        }
        static::$guardableColumns[get_class($this)] = $columns;
    }

    return in_array($key, static::$guardableColumns[get_class($this)]);
}

Each model has to do a lookup of the schema to first check if the column being set is actually a real column on the table. And it sets it statically, so if you created multiple models in a request, it would only do the lookup once. But it is doing it on each request for each model.

This extra database query is not done if you are using fillable instead. You might label this as a micro-optimization, but it's something to be aware of.

And are you wondering why Laravel is running this query? It's a security issue patched way back in Laravel 6 related to JSON columns.

Here to help,

Joel

P.S. Fillable vs guarded is discussed in more detail in our book, Mastering Laravel Validation Rules.

Toss a coin in the jar if you found this helpful.
Want a tip like this in your inbox every weekday? Sign up below 👇🏼

Level up your Laravel skills!

Each 2-minute email has real-world advice you can use.