Laravel Slugable is a lightweight Laravel trait that automatically generates slugs from model fields like title
, name
, or any custom source — and stores it in a customizable destination field such as slug
, etc.
Perfect for blogs, e-commerce, CMS, or any app that needs clean, readable, SEO-friendly URLs with multi-language support.
- 🚀 Auto-generate slug on model creation
- 🔄 Optional re-generation on model update
- 🛠️ Customizable source and destination fields
- 🌍 Multi-language support (Persian, Arabic, English)
- 🔢 Automatic conversion of non-English numbers
- 🧹 Special character cleaning for each language
- 🔍 Unique slug enforcement with counter
- 📏 Max length enforcement
- 💡 No external dependencies
- ⚡ Static helper method for non-model usage
- 🧵 Thread-safe implementation
- 🔒 Type-safe operations
Install Package:
composer require rayiumir/laravel-slugable
After Publish Files:
php artisan vendor:publish --provider="Rayiumir\\Slugable\\ServiceProvider\\SlugableServiceProvider"
Calling HasSlugable
in Models Post.php
:
class Post extends Model
{
use HasSlugable;
}
Provided that the title
and slug
fields are in the database.
class Post extends Model
{
use HasSlugable;
protected $slugSourceField = 'name'; // Field to generate slug from
protected $slugDestinationField = 'slug'; // Field to store slug in
}
class Post extends Model
{
use HasSlugable;
protected $slugLanguage = 'fa'; // Supports 'fa', 'ar', 'en'
}
class Post extends Model
{
use HasSlugable;
protected $slugSeparator = '_'; // Default: '-'
protected $slugMaxLength = 100; // Default: 250
protected $slugForceUpdate = true; // Force regenerate on update
protected $slugShouldBeUnique = false; // Disable unique enforcement
}
You can generate slugs without a model instance:
$slug = Post::generateSlugFrom('My Post Title', [
'language' => 'en',
'separator' => '_',
'maxLength' => 50
]);
// Create with auto-slug
$post = new Post();
$post->title = 'Laravel ۱۲'; // Persian numbers
$post->save();
echo $post->slug; // Output: laravel-12
// Force update slug
$post->slugForceUpdate = true;
$post->title = 'New Laravel ۱۲';
$post->save();
echo $post->slug; // Output: new-laravel-12
// Generate slug without saving
$slug = Post::generateSlugFrom('Custom Title');
The trait automatically handles:
- Persian/Arabic numbers conversion
- ZWNJ (Zero-width non-joiner) removal for Persian
- Tatweel removal for Arabic/Persian
- Language-specific character preservation
- Add index to your slug column for better performance:
Schema::table('posts', function (Blueprint $table) {
$table->string('slug')->unique()->index();
});
- For large tables, consider adding the slug generation in a migration:
Post::chunk(200, function ($posts) {
$posts->each->generateSlug();
});
- Use the static method when generating slugs in migrations:
$posts->each(function ($post) {
$post->slug = Post::generateSlugFrom($post->title);
$post->save();
});
- The trait uses efficient string operations
- Language patterns are defined as constants for better performance
- Slug uniqueness check is optimized to exclude current model
- Works with soft-deleted models