Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Raymond's avatar

How to validate a slug unique in Laravel 5?

I have the following controller: http://laravel.io/bin/ByJo0 And the request: http://laravel.io/bin/23KkE And the model: http://laravel.io/bin/LNqm0

Problem is and what i am trying to achieve is to make the slug before running the validation, without changing the formRequest made by Laravel,

Laracasts is really great, but what i am always missing, are these particular things like how to update a slug, or how to update an unique field.

0 likes
10 replies
bashy's avatar

Have to pass the current ID to the exclude part of the validation.

RavanScafi's avatar

You want to make sure that the slug is unique on creating and also on updating, except when it hasn't changed?

On Create:

return [
        'slug'  => 'required|unique:articles',
];

On Update: (assuming you are accessing it with /articles/{slug})

$article = $this->route()->getParameter('articles');

return [
    'slug' => "required|unique:articles,slug,{$article->slug},slug",
]
1 like
RavanScafi's avatar

Just my two cents: One thing that I do is to allow form to be submitted without a slug, so it's auto-generated. If the slug already exists, a number is appended to make it unique.

Here's the helper that I'm using:

/**
 * Generate a unique slug.
 * If it already exists, a number suffix will be appended.
 * It probably works only with MySQL.
 *
 * @link http://chrishayes.ca/blog/code/laravel-4-generating-unique-slugs-elegantly
 *
 * @param Illuminate\Database\Eloquent\Model $model
 * @param string $value
 * @return string
 */
function getUniqueSlug(\Illuminate\Database\Eloquent\Model $model, $value)
{
    $slug = \Illuminate\Support\Str::slug($value);
    $slugCount = count($model->whereRaw("slug REGEXP '^{$slug}(-[0-9]+)?$' and id != '{$model->id}'")->get());

    return ($slugCount > 0) ? "{$slug}-{$slugCount}" : $slug;
}

(On a future refactor, I would use it with a trait and an acessor on model, instead of a helper, but it's up to you)

3 likes
kkiernan's avatar

I think Raymond's (any my) issue is a little bit different here. A mutator is setting the slug based on some other value (let's say an article's title). The issue, it seems, is that the FormRequest validation is done before the mutator sets the slug value on the model, and so validation either fails (if the slug is required) or ignores the slug altogether.

How do you guys generate slugs? That is, do you include a slug input in the html form? Are you validating with a FormRequest or handling it in the controller (I'd like to avoid this)?

Nick385's avatar

I was trying this lesson https://laracasts.com/lessons/unique-slugs-in-laravel To make it work change this

static::whereRaw("slug REGEXP '^{$model->slug}(-[0-9]*)?$'")

To

static::whereRaw("slug = '$model->slug' or slug LIKE '$model->slug-%'")

Complete code put this on you're model

   public static function boot()
   {
       parent::boot();

       static::creating(function($model) {
           $model->slug = str_slug($model->ToBeSluggified);// change the ToBeSluggiefied

           $latestSlug =
               static::whereRaw("slug = '$model->slug' or slug LIKE '$model->slug-%'")
                   ->latest('id')
                   ->value('slug');
           if ($latestSlug) {
               $pieces = explode('-', $latestSlug);

               $number = intval(end($pieces));

               $model->slug .= '-' . ($number + 1);
           }
       });
   }
1 like
cawecoy's avatar

Supposing you want to use the attribute title to be sluggified, use this mutator in your model:

    public function setTitleAttribute($value) {
        $this->attributes['title'] = $value;
        $slug = str_slug($value, '-');
        $id = $this->attributes['id'];
        $slugCount = count(Model::whereRaw("(slug = '$slug' or slug LIKE '$slug-%') and id != $id")->get());
        $this->attributes['slug'] = $slugCount == 0 ? $slug : $slug.'-'.$slugCount;
    }

Thanks to @Nick385 and @RavanScafi I've mixed both solutions to come to the above one.

1 like
antoniocusro's avatar

@cawecoy Your solution is really good, but it doesn't work for new models, because they don't have an ID attribute already, so it will result in an Exception. Maybe just add a check for $this->exists before trying to get the id and only try to exclude the id in the whereRaw clause if the model is not new.

Please or to participate in this conversation.