Very often there is a need to refer to a model by slug. For example, you may want to hide a real model ID in the URL and replace it with a slug for better readability. Slugs must contain only digits or letters and hyphens. And they must be unique.
In this article we will explain how to create a unique slug in Laravel for models using spatie/sluggable package.
Table of Contents
Creating Unique Slug in Laravel
I assume that you have installed Laravel. If not, see this article.
1. Prepare Model
Imagine, that you have the Article model that has a title field and you want to create a slug based on this field. Let’s create the model and the migration for it:
php artisan make:model Article
php artisan make:migration CreateArticlesTable
return new class extends Migration {
public function up()
{
Schema::create("articles", function (Blueprint $table) {
$table->id();
$table->string("title");
$table->text("content");
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists("articles");
}
};
Then, migrate it using this command:
php artisan migrate
2. Make Factory
You can use the factory for this example to fill the articles table and test how the slugs will be generated. Use this command:
php artisan make:factory ArticleFactory
The factory will appear in the database/factories directory. You don’t need to specify the model, it will be obtained automatically from the class name.
class ArticleFactory extends Factory
{
public function definition()
{
return [
"title" => $this->faker->text(100),
"content" => $this->faker->text(200),
];
}
}
2. Install Package
You can generate slugs manually. But it would be more convenient if you use the spatie/laravel-sluggable package. Install it using this command:
composer require spatie/laravel-sluggable
3. Configure the Model
Your model should have Spatie\Sluggable\HasSlug trait and implement method getSlugOptions() that will return the SlugOptions class. So, change your Article class to this:
use Illuminate\Database\Eloquent\Model;
use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;
class Article extends Model
{
use HasSlug;
public function getSlugOptions(): SlugOptions
{
return (new SlugOptions())
->generateSlugsFrom("title")
->saveSlugsTo("slug")
->usingSeparator("-");
}
}
In the getSLugOptions() method you can configure slug-generating options. In this example slugs will be generated based on the title field and saved to the slug field. If the slug needs a separator, the generator uses a hyphen. Now your model is ready for using slugs. You can find more configuration examples in the official documentation for the package.
4. Test Auto Generation
By default, slugs will be generated at the time of model creation. So, let’s create a command that will generate a few models:
php artisan make:command CreateDummyArticlesCommand
Paste this code into the handle() method:
public function handle(): int
{
Article::factory()
->count(10)
->create();
return self::SUCCESS;
}
This code will create ten articles with unique slugs. Don’t forget to change $signature to dummy:articles:create and run this command:
php artisan dummy:articles:create
After this you can check generated slugs in the database or create any command or resource that will display articles for you.

5. Generate Slugs for Permalinks
By default this package updates slugs when you update data in your model. If you use slugs in URLs for SEO, this is not good behavior. You make slugs immutable. Add method the doNotGenerateSlugsOnUpdate() call to the getSlugOptions() method:
public function getSlugOptions(): SlugOptions
{
return (new SlugOptions())
->generateSlugsFrom("title")
->saveSlugsTo("slug")
->usingSeparator("-")
->doNotGenerateSlugsOnUpdate();
}
6. Generate Slugs Manually
When you disable slug generation on model updating and you have old models, the package will not generate slugs for them. You should do it manually. Just call the generateSlug() method for the needed model. For example, you can create a command that will update slugs for all articles:
php artisan make:command ArticleSlugsUpdateCommand
Then, paste this code into the handle() method:
$articles = Article::all();
foreach ($articles as $article) {
/** @var Article $article */
$article->generateSlug();
}
return self::SUCCESS;
Now, you can run this command and update slugs for all models.
Wrapping Up
In this short article we have explained how to generate unique slugs in Laravel for Eloquent models. As you can see it is pretty simple. Just install the package, add configuration and it will do all the work for you. What package do you use for generating slugs? Tell us using the comment form below.