History, events and immutability
SlugChanged
Polyslug\Events\SlugChanged fires whenever a current slug is created or changed —
previous is null on first generation. It is the natural hook for cache busting, search
reindexing, or sitemap regeneration:
use Polyslug\Events\SlugChanged;
Event::listen(function (SlugChanged $event) {
// $event->model, $event->locale, $event->slug, $event->previous
});
SlugRedirected
Enable polyslug.analytics.enabled to also dispatch Polyslug\Events\SlugRedirected on
every self-healing redirect — the requested key, the canonical URL, the model, the locale
and the status. It is a fire-and-forget hook for measuring link rot, warming a cache, or
purging a CDN.
// config/polyslug.php
'analytics' => ['enabled' => true],
It is off by default, and even when on it is only the event dispatch — nothing writes synchronously on the hot path unless your listener does. The event is keyed on the stable model rather than on the churny slug, so a rename does not double-count.
Both payloads are listed in the events reference.
Immutable slugs
Freeze a model's slug after its first generation so later edits to the source never move it — ideal for permalinks:
#[Polyslug(source: 'title', immutable: true)]
Editing the title of a frozen model is then a no-op as far as the URL is concerned: no new slug, no redirect, no history entry. Use it where the URL is a citation — a published regulation, an issued invoice, a press release — and correcting a typo in the headline must not move the document.
setSlug() remains the deliberate escape hatch for setting a locale's slug explicitly.
Reading the history
Superseded slugs are kept so old URLs keep resolving, and read newest-first:
$model->slugHistory(); // superseded slugs for the active locale, newest first
$model->slugHistory('de'); // for an explicit locale
History is per locale, and it holds only superseded slugs — the current one comes from
currentSlug(). Nothing prunes it, which is what keeps every URL you have published
resolvable; see Gone and superseded for the deliberate ways to
retire a URL.