cviebrock/eloquent-sluggable
Generate SEO-friendly, unique slugs for Laravel Eloquent models automatically. Configure sources, separators, max length, reserved words, and update behavior; supports soft deletes and route model binding. Includes a SlugService and extensible hooks.
Install the package via Composer matching your Laravel version (e.g., composer require cviebrock/eloquent-sluggable:^11.0 for Laravel 11). Publish the config file with php artisan vendor:publish --provider="Cviebrock\EloquentSluggable\ServiceProvider". In your model, add the Sluggable trait and implement the required sluggable() method — define at least one slug field with its source (e.g., 'slug' => ['source' => 'title']). Run a migration to add the slug column (nullable string) to your table. After creating a model instance (e.g., via create()), the slug is automatically generated and accessible as $model->slug.
title) for most resources like posts, products, or pages.['author.last_name', 'author.first_name']) or include static text (e.g., ['category.name', 'static' => 'post']).sluggable() to store distinct slugs (e.g., one for SEO, one for API).SlugService::createSlug(Post::class, 'slug', 'Test Title') in AJAX endpoints to preview uniqueness or validate user input before saving.replicate() (e.g., "my-post" → "my-post-1"), ideal for content duplication workflows.slugging and slugged model events for logging, analytics, or conditional slug rejection (return false in slugging to skip).sluggableEvent() return SluggableObserver::SAVED to include IDs in source (e.g., 'source' => ['title', 'id']).null produce no slug; false → "0", true → "1", and 0/1 → "0"/"1". Always validate or sanitize sources (e.g., Str::slug($value) in a mutator) if needed.unique behavior: By default, uniqueness checks exclude trashed models (includeTrashed: false). Enable to include soft-deleted conflicts — avoid accidentally colliding with old entries during reverts.maxLength truncation: When cutting off long slugs, words are kept intact by default (maxLengthKeepWords: true). Set to false for strict character limits (e.g., maxLength: 50).reserved config to block problematic words (e.g., ['admin', 'dashboard']) or model-specific reserved strings via scopeFindSimilarSlugs override.onUpdate: true to enforce regeneration (costs an extra update query).sluggableEvent() returns SAVED if you rely on model IDs in sources — the default changed to SAVING for performance but breaks ID-based sources.dd($post->getSlugOptions()) to inspect resolved configuration during debugging — helpful for verifying overrides and trait behavior.How can I help you explore Laravel packages today?