aesircloud / sluggable
A Laravel package to automatically generate slugs for models
Requires
- php: ^8.3
- illuminate/database: ^11.0|^12.0
- illuminate/support: ^11.0|^12.0
Requires (Dev)
- orchestra/testbench: ^9.10
- pestphp/pest: ^2.34
README
sluggable
is a Laravel package that generates unique slugs for Eloquent models. It can be used to automatically generate slugs when creating or updating models, with flexible options controlled by both a config file and model-level properties.
Installation
You can install the package via Composer:
composer require aesircloud/sluggable
Publish the configuration file
php artisan vendor:publish --provider="AesirCloud\Sluggable\SluggableServiceProvider"
Usage
Add the Sluggable
trait to your model:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use AesirCloud\Sluggable\Traits\Sluggable; class Post extends Model { use Sluggable; protected $fillable = ['title', 'slug']; /** * Optionally override the default slug source field. * * By default, the package uses whatever is set in 'sluggable.source' * or falls back to 'name' on your model. Here, we explicitly use 'title'. */ protected $slugSource = 'title'; /** * If you want to allow the slug to be updated automatically when 'title' changes: */ protected $slugUpdatable = true; /** * If you want a different slug column in your database table: */ protected $slugColumn = 'url_slug'; }
2. Migrate the Slug Column
Ensure your table has a suitable column for the slug:
php artisan make:migration add_slug_to_posts_table --table=posts
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { public function up(): void { Schema::table('posts', function (Blueprint $table) { // Make sure it's unique or at least indexed if you rely on uniqueness. $table->string('slug')->unique()->after('title'); }); } public function down(): void { Schema::table('posts', function (Blueprint $table) { $table->dropColumn('slug'); }); } };
3. Configuration Options
Open config/sluggable.php
to see the available options. You can override any of these in your model by defining the corresponding property.
return [ 'source' => 'name', 'column' => 'slug', 'update' => false, 'max_length' => 255, 'scopes' => [], // e.g. ['category_id'] to scope uniqueness ];
- source: The default field the slug is generated from if you don’t set $slugSource in the model.
- column: The column to store the slug.
- update: Set true to automatically regenerate a slug when the source field changes on update.
- max_length: Truncates the slug (plus space for numeric suffixes) to this length if specified.
- scopes: Array of columns to scope uniqueness (e.g., if you only want unique slugs per category_id).
4. Route Model Binding (Optional)
If you want to use the slug in your routes, you can override getRouteKeyName() in your model:
public function getRouteKeyName() { return 'slug'; }
Then reference it in your routes:
Route::get('/posts/{post:slug}', function (App\Models\Post $post) { return $post; });
Changelog
Please see CHANGELOG for more information what has changed recently.
Security
If you've found a bug regarding security please mail security@aesircloud.com instead of using the issue tracker.
LICENSE
The MIT License (MIT). Please see License file for more information.