---
title: "Slugs — Posts for Laravel | Roundly"
description: "Per-locale slugs generated from the title, unique per locale with database indexes, normalised manual input and backfill commands."
url: https://roundly-consulting.com/open-source/docs/posts-for-laravel/slugs
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Posts for Laravel](https://roundly-consulting.com/open-source/docs/posts-for-laravel.md)

# Slugs

Posts, categories and tags keep a per-locale slug map, managed by sluggable-for-laravel. Post slugs are generated from posts.slugs.source (title by default); category and tag slugs from name.

- Generated for every locale that has a source value and that a lookup can resolve: the current locale, posts.locales.fallback and sluggable.locales.supported (by default app.locale + app.fallback\_locale). A blank title, or one that slugifies to nothing, is skipped.
- Filled, never rewritten: a save that changes the model fills locales that have no slug yet; existing slugs stay put, so a title edit never breaks a URL.
- Unique per locale (posts.slugs.unique): collisions get -2, -3, … in bounded, batched probes. Trashed rows and rows hidden by global scopes count as taken, and the per-locale unique indexes plus an automatic retry close the race between two concurrent saves.
- Manual slugs are normalised and made unique — Custom Slug becomes custom-slug, taken becomes taken-2 — including the ones CreatePostAction receives.

## Reading slugs

```php
$post->currentSlug();        // current locale → posts.locales.fallback → any locale
$post->slugFor('sk');        // exactly one locale, no fallback
$post->slugMap();            // ['en' => 'hello-world', 'sk' => 'ahoj-svet'] — with sk in sluggable.locales.supported

// Swappable model: find through the facade, not Post::findBySlug() (which is always the packaged class)
Posts::findBySlug('hello-world');          // current locale → fallback → any locale
Posts::findBySlug('ahoj-svet', 'sk');      // exactly one locale — null on a default install, which has no sk slug
Posts::query()->whereSlug('hello-world')->first();
```

A locale outside that list gets no slug, even when the post has a title in it: on a default English install a Slovak title produces no sk slug, so Posts::findBySlug('ahoj-svet', 'sk') returns null. List every content locale in sluggable.locales.supported — before migrating, so the per-locale unique indexes cover them — or install translatable-for-laravel, whose locales sluggable then uses.

## Manual slugs

```php
$post->setTranslation('slug', 'en', 'Custom Slug')->save();
$post->slugFor('en');        // 'custom-slug' — or 'custom-slug-2' when it is taken
```

## Backfill and maintenance

A no-op save() changes nothing, so backfill locales without a slug — for example after adding a language — with sluggable’s commands. Run the duplicates check before building indexes on existing data: older versions ignored trashed posts when checking slugs, so a live and a trashed post may share one.

```bash
# Backfill slugs for locales that have none yet (add --dry-run to preview)
php artisan sluggable:regenerate "RoundlyConsulting\Posts\Models\Post" --mode=missing

# List slugs a unique index would reject — run before indexing existing data
php artisan sluggable:duplicates "RoundlyConsulting\Posts\Models\Post"

# Build the per-locale unique indexes (e.g. for a locale added after migrate)
php artisan sluggable:indexes "RoundlyConsulting\Posts\Models\Post"
```

Run the same commands for RoundlyConsulting\\Posts\\Models\\Category and RoundlyConsulting\\Posts\\Models\\Tag.

## 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 crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## 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.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/posts-for-laravel.md)
