Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Sluggable Laravel Package

aesircloud/sluggable

Aesircloud Sluggable is a Laravel package for automatically generating URL-friendly slugs for Eloquent models. It offers configurable source fields, uniqueness handling, and simple integration, helping developers create clean, SEO-friendly routes with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require aesircloud/sluggable. Version 1.2.0 adds Laravel 13 support; verify your composer.json platform constraints allow the Laravel version you run, especially if you are upgrading an existing app.
  • Laravel package discovery should register the service provider automatically. If you need to customize behavior, publish the package config (php artisan vendor:publish --tag=sluggable-config or the tag documented in the README) and review the defaults before writing code.
  • Look first at the package README and the published config file. Identify the trait name, the source-field option, the slug-column option, and any uniqueness/regeneration flags. Those four settings drive most day-to-day usage.
  • Add the package trait to the model that needs URL-friendly identifiers, and ensure the target column exists with an appropriate length and a unique index. For a blog post, the first use case is typically: Post has title, add slug, generate on create, and route to posts by slug.
  • Confirm route binding early. If the package does not override getRouteKeyName(), add that method to the model or resolve records explicitly with the slug column.
Schema::table('posts', function (Blueprint $table) {
    $table->string('slug')->unique()->after('title');
});

Implementation Patterns

  • Trait-on-model configuration. Use the package trait on each sluggable model and declare the source attribute(s) explicitly. Keep the configuration close to the model rather than relying on global defaults, so different models can use different source columns.
  • Generate on create, not on every save. The safest default is to generate a slug only when the slug column is empty. Regenerating on every update silently changes public URLs and breaks bookmarks, canonical links, and inbound links. If titles are editable, treat slug changes as an explicit editorial action.
  • Uniqueness handling. Let the package resolve collisions by appending a numeric suffix, but still enforce uniqueness at the database level. Application-level checks are vulnerable to concurrent writes; the unique index is the real guarantee.
  • Route model binding. Either override getRouteKeyName() to return the slug column or use explicit binding in routes. Add a fallback lookup by ID or a redirect strategy if legacy URLs must keep working.
  • Backfilling existing records. For an existing table, add a nullable slug column first, backfill in chunks, then add the unique index. Do not run a single massive update inside a migration on a large table.
Post::query()
    ->whereNull('slug')
    ->chunkById(500, function ($posts) {
        foreach ($posts as $post) {
            $post->save(); // or call the package's generation method explicitly
        }
    });
  • Multiple source fields. If the package supports an array of sources, order them by preference and provide a deterministic fallback (for example, title first, then a short identifier). Avoid sources that change frequently.
  • Custom slug normalization. For non-Latin titles, configure transliteration or provide a custom slug generator if the package exposes one. Decide whether to preserve Unicode slugs or transliterate to ASCII; this affects SEO and URL readability.
  • Soft deletes. If models are soft-deleted, confirm whether uniqueness checks include trashed records. A unique index that includes soft-deleted rows can block reuse of a slug; a partial index or scoped uniqueness check may be needed depending on your database.
  • Testing. In factories, set slugs explicitly when the test cares about a specific URL. Add at least one test that creates two records with the same title and asserts distinct slugs, and one test that asserts the database rejects a duplicate slug insert.
  • API resources. Expose the slug as a stable public identifier, but keep the numeric ID available for internal references. Do not make the slug the primary key; keep it a unique alternate key.

Gotchas and Tips

  • Laravel 13 compatibility is the headline change in 1.2.0. No new slug-generation features are indicated. Treat this as a maintenance release: run your test suite after upgrading, and check that your application's Laravel version and PHP version satisfy the package's constraints.
  • Mass assignment. Ensure the slug column is either fillable or guarded appropriately. If the package sets the slug internally, avoid accidentally overwriting it through create() or update() payloads.
  • Column length and indexing. MySQL with utf8mb4 has index-length limits. A string('slug') with a unique index may fail on older MySQL configurations; use a sensible maximum length and consider a prefix index only as a last resort.
  • Race conditions. Two simultaneous creates with the same title can both pass an application-level uniqueness check. Always keep the database unique constraint and be prepared to retry on duplicate-key exceptions.
  • Slug churn. Changing a slug because a title changed is the most common production regret. Freeze slugs after creation, or implement a redirect table that maps old slugs to new ones.
  • Empty or punctuation-only sources. Titles like ??? or emoji-only strings can produce empty slugs. Configure a fallback (ID, UUID fragment, or a dated string) and test it.
  • Config caching. If you publish and edit the package config, run php artisan config:cache in production deployments. Stale config can make it appear that package options are ignored.
  • Event side effects. If slug generation happens in model events, saveQuietly(), observers, and bulk updates may bypass or unexpectedly trigger it. Be explicit about which write paths generate slugs.
  • Debugging. Inspect the model's attributes immediately before and after save, check whether the trait's generation method is being called, and verify the unique index exists in the actual database—not just in the migration file.
  • Extension points. Prefer overriding the package's documented slug-generation method or binding a custom generator over forking the package. If the package dispatches events around slug generation, use them for logging or audit trails rather than for core uniqueness logic.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource