Back to all posts

Model mutators overriding explicit slug values in seeders!

Sixtus Miracle AgboSixtus Miracle Agbo
1 min read
Model mutators overriding explicit slug values in seeders!

As Laravel developers, we often rely on model features to handle transformations automatically. However, these convenient features can sometimes lead to subtle bugs. Today, I want to share an experience of a bug I squashed😂😮‍💨

The Problem

In a Laravel blog project, I was using data population techniques to initialize content:

// In PostSeeder.php
Post::create([
  'slug' => 'dummy-slug-example',
  'title' => 'Dummy Title: Lorem Ipsum Example',
  // other attributes…
]);

Despite explicit settings, I noticed unexpected behaviors. This was puzzling because the model configuration seemed correct.

Investigating the Root Cause

After some debugging, I discovered an issue in the model’s method:

public function setTitleAttribute($value)
{
    $this->attributes['title'] = $value;
 
    if (!$this->exists) {
        $this->attributes['slug'] = Str::slug($value);
    }
}

The method was automatically generating values whenever a new model was being created, regardless of whether values had already been manually set.

The Solution

The fix was elegantly simple. We just needed to modify the mutator to respect manually set slug values:

public function setTitleAttribute($value)
{
    $this->attributes['title'] = $value;
 
    // Only auto-generate slug if it hasn't been manually set
    if (!$this->exists && !isset($this->attributes['slug'])) {
        $this->attributes['slug'] = Str::slug($value);
    }
}

By adding the `!isset($this->attributes[‘slug’])` condition, we ensure the mutator only generates a slug when one hasn’t already been provided. This way, our seeder’s explicitly set slug values are preserved.

Lessons Learned

This experience highlights a few important lessons:

1. Understand Laravel’s Attribute Setting Sequence: When using `create()` or `new Model()` followed by setting attributes, be aware of the order in which attributes are set and how mutators might interact with them.

2. Defensive Mutator Design: When writing mutators that automatically set other attributes, always check if those attributes already have values before overriding them.

3. Test Your Seeders: It’s easy to overlook issues in seeders since they’re often run once and forgotten. Consider writing tests specifically for your seeding process.

This may seem like a small issue, but in a production environment, having the wrong slugs could impact SEO, user experience, and even break existing links. Taking care to understand how Laravel’s underlying features work together can save hours of debugging down the line.

Share this post
Sixtus Miracle Agbo

Sixtus Miracle Agbo

Full-Stack Developer crafting high-performance web and mobile applications. I write about software development, technology, and lessons learned building real products.

Get in touch