All packages
Sluggable for Laravel
Events & exceptions
Listen for SlugChanged to refresh sitemaps, caches or search indexes whenever a slug changes:
use RoundlyConsulting\Sluggable\Events\SlugChanged;
Event::listen(SlugChanged::class, function (SlugChanged $event): void {
// $event->model, ->column, ->locale, ->previous, ->current, ->reason (ChangeReason)
Cache::forget('sitemap');
});| Event | Payload | When |
|---|---|---|
SlugChanged (after commit) | model, column, locale, previous, current, reason (ChangeReason) | Once per persisted change. |
SlugCollisionRetried | modelClass, column, attempt | Every race retry. |
SlugsRegenerated | modelClass, report | End of a regeneration run / queued chunk. |
- SlugChanged implements ShouldDispatchAfterCommit — never fired for a rolled-back save. It fires once per persisted change, manual ones included, and once per changed locale for maps.
- It is not dispatched inside withoutGeneration() or with sluggable:regenerate --without-events.
- ChangeReason is one of Generated, Regenerated, Manual, CollisionRetry or Restored.
Exceptions
Every exception extends the abstract SluggableException (a RuntimeException). Messages name the model class, column and locale — never another row’s value.
| Exception | Thrown when |
|---|---|
InvalidSlugDefinitionException | An invalid definition or config value — duplicate columns, several route keys, a bad separator, maxLength out of range, a missing contract, a missing scope value and similar. |
InvalidLocaleException | A malformed locale code you supply (malformed keys in stored maps are skipped instead). |
SlugGenerationException | Probing exhausted, an empty source under Fail, retries used up, an index/definition mismatch, invalid custom-slugger output or collision suffix, affixes that leave no room for the slug, an unsafe manual value or a Strict manual value over maxLength. |
SlugAlreadyTakenException | A Strict manual value is already taken. |
SlugLockedException | A manual change to a locked slug; the message is the sluggable::validation.locked translation, in the current locale. |
SlugMovedException | A retired slug was requested — renders the history redirect; implements ShouldntReport. |
UnsupportedDriverException | Index DDL on an unsupported driver (e.g. SQL Server). |
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.