eloquent-sluggable: Automatic URL Slug Generation for Laravel Models
Easy creation of slugs for your Eloquent models in Laravel
At a glance
- What is it?
- eloquent-sluggable is a Laravel package that automatically generates URL-friendly slugs for Eloquent model attributes. It handles uniqueness, duplicate detection, and slug regeneration through a trait and a configuration array, removing the need for manual slug management code.
- Who is it for?
- eloquent-sluggable is the right tool for a Laravel project that needs automatic, unique slug generation for Eloquent models with minimal configuration. It is the wrong choice for applications not using Laravel's Eloquent ORM, for Lumen projects (support has been dropped), or for teams that need slug generation outside the Eloquent model lifecycle.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 72 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 26, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What a Slug Is and What eloquent-sluggable Automates
A slug is a URL-safe string derived from a longer piece of text, typically a title. The URL `http://example.com/post/my-dinner-with-andre-francois` is friendlier and better for search engine optimization than `http://example.com/post/My+Dinner+With+Andr%C3%A9+%26+Fran%C3%A7ois`, even though both refer to the same post.
Without a slug library, a developer must write code to normalize the source string, strip non-URL-safe characters, handle transliteration (converting accented characters like 'é' to 'e'), enforce a maximum length, and detect collisions when two posts have the same title. eloquent-sluggable handles all of these steps and integrates the result into the Eloquent model lifecycle so the slug is generated automatically when the model is saved.
The last push was on 2026-07-20. The package is licensed under MIT.
Installation and Initial Model Setup
The package version number tracks the Laravel major version. For Laravel 13, install version 13.x:
composer require cviebrock/eloquent-sluggableThe service provider registers automatically via Laravel's package auto-discovery. To override default configuration:
php artisan vendor:publish --provider="Cviebrock\EloquentSluggable\ServiceProvider"To add slug generation to a model, apply the `Sluggable` trait and define the `sluggable()` method:
use Cviebrock\EloquentSluggable\Sluggable;
class Post extends Model
{
use Sluggable;
public function sluggable(): array
{
return [
'slug' => [
'source' => 'title'
]
];
}
}The `slug` key in the returned array is the database column where the slug will be stored. The `source` key identifies the model attribute to build the slug from. The column must already exist in the database, created as a `NULLABLE` column through a migration.
Creating and Retrieving Slugs
Once the trait is applied, saving a model generates the slug automatically:
$post = Post::create([
'title' => 'My Awesome Blog Post',
]);
echo $post->slug; // my-awesome-blog-postThe slug is accessible as a model attribute like any other database column.
When a model is replicated using Eloquent's `replicate()` method, eloquent-sluggable re-slugs the copy to ensure uniqueness:
$newPost = $post->replicate();
// $newPost->slug is "my-awesome-blog-post-1"This prevents two records from having the same slug value, which would cause ambiguous URL resolution.
The package fires events during slug generation, allowing application code to hook into the process. The specific event names are documented in the README under the Events section.
Configuration: Uniqueness, Length, and Update Behavior
The `sluggable()` method returns a configuration array with a range of options. Key options include:
`unique`: controls whether generated slugs must be unique across the table. When `true` (the default), collisions are resolved by appending a numeric suffix. `uniqueSuffix` and `firstUniqueSuffix` control the suffix format and the starting value.
`separator`: the character used between words. The default is a hyphen.
`maxLength` and `maxLengthKeepWords`: `maxLength` sets a character limit for the slug. When `maxLengthKeepWords` is `true`, the truncation happens at a word boundary rather than mid-word.
`onUpdate`: whether to regenerate the slug when the source attribute changes. The default is `false`, meaning the slug generated at creation is permanent. Setting it to `true` means editing a post title will change its URL.
`includeTrashed`: when set to `true`, soft-deleted records are included when checking for uniqueness.
`reserved`: an array or a callable returning values the slug must never match, such as reserved route names.
`method`: a custom callable for slug generation, overriding the default string normalization. This allows integration with locale-specific transliteration libraries if the default behavior is insufficient.
SlugService, Route Model Binding, and Scope Helpers
The `SlugService` class provides slug generation outside of the save lifecycle. It can produce a slug for a given string and model class without creating a record, which is useful for previewing slugs in forms or API responses before the model is saved.
For route model binding, Laravel's routing system can resolve a model from a slug in the URL rather than from the database ID. The package documents this in a separate `ROUTE-MODEL-BINDING.md` file. The binding configuration allows a route like `/posts/{post:slug}` to automatically look up the Post model by its `slug` column.
The `SluggableScopeHelpers` trait is a separate trait that adds query scopes to the model, documented in `SCOPE-HELPERS.md`. These scopes support finding a model by slug and finding records with similar slugs, which can be useful when building URL preview or duplicate detection features.
Limitations: Lumen, Database Coupling, and Laravel Version Lock
The package dropped support for Laravel Lumen. The README includes an explicit note that Lumen is no longer supported. Applications running on Lumen cannot use this package.
The versioning scheme ties the package to a specific Laravel major version: version 13.x requires Laravel 13, version 12.x requires Laravel 12, and so on. A major Laravel upgrade requires a corresponding package upgrade, and breaking changes between versions are documented in UPGRADING.md and CHANGELOG.md. The README notes that older versions of the package exist for older Laravel versions but are no longer maintained.
Slug generation happens within the Eloquent model lifecycle. If your application inserts records directly through raw SQL or through a different ORM, the slug will not be generated. The package provides no external CLI or batch tool for slugging existing records.
The closest alternative is spatie/laravel-sluggable, another slug generation package for Laravel that also uses a trait-based approach. The two packages cover similar ground. The spatie package is part of the larger Spatie ecosystem of Laravel packages, which may matter for teams already using other Spatie packages. Both support unique slugs, configurable separators, and source attribute configuration. The difference in approach is primarily in configuration syntax and extensibility hooks.
Editorial conclusion
eloquent-sluggable is the right tool for a Laravel project that needs automatic, unique slug generation for Eloquent models with minimal configuration. It is the wrong choice for applications not using Laravel's Eloquent ORM, for Lumen projects (support has been dropped), or for teams that need slug generation outside the Eloquent model lifecycle. The package version must match the Laravel major version; confirm this before upgrading Laravel to a new major release.
Frequently asked questions
How do I create slugs in Laravel with eloquent-sluggable?
Install the package with composer require cviebrock/eloquent-sluggable, add a NULLABLE slug column via migration, apply the Sluggable trait to your model, and define a sluggable() method returning an array mapping the slug column to its source attribute. The slug is generated automatically when the model is saved.
Does eloquent-sluggable support Lumen?
No. The README explicitly states that Lumen support has been dropped.
What happens when two models have the same slug in eloquent-sluggable?
When the unique configuration option is true (the default), the package appends a numeric suffix to the slug to resolve the collision. For example, my-post becomes my-post-1 and then my-post-2 for subsequent duplicates. The firstUniqueSuffix option controls the starting suffix value.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/cviebrock-eloquent-sluggable)