novius/laravel-filament-slug
composer require novius/laravel-filament-slug
TextInput for slugs in a Filament Resource form. Start with a basic setup where the slug is auto-generated from a title field:
use Novius\FilamentSlug\Fields\Slug;
public static function form(Form $form): Form
{
return $form->schema([
TextInput::make('title')->required(),
Slug::make('slug')
->fromField($title)
->required(),
]);
}
Basic Slug Generation:
Bind the slug to a TextInput (e.g., title) using fromField():
Slug::make('slug')->fromField($title);
This ensures the slug updates dynamically as the title changes.
Conditional Slug Generation: Skip slug generation based on application logic (e.g., if another field is populated):
Slug::make('slug')
->fromField($title, fn (Get $get) => empty($get('custom_slug')));
This is useful for cases where a manual slug is preferred.
Manual Slug Editing: Allow users to manually edit the slug while retaining auto-generation:
Slug::make('slug')
->fromField($title)
->live(false); // Disable live updates
This is helpful when users need to override the auto-generated slug.
Custom Slug Formatting:
Use format() to customize the slug structure (inherited from TextInput):
Slug::make('slug')
->fromField($title)
->format('{title}-{id}'); // e.g., "my-title-123"
This is useful for adding dynamic segments like IDs or categories.
Validation and Rules: Apply validation rules (e.g., uniqueness, regex) to the slug:
Slug::make('slug')
->fromField($title)
->rules([
'unique:posts,slug',
'regex:/^[a-z0-9\-]+$/i',
]);
Integration with Filament Tables: Display the slug in Filament tables for better UX:
TableColumn::make('slug')->searchable()->sortable();
Create Workflow:
Use the slug field in the create() form to auto-generate slugs for new records.
public static function createForm(Form $form): Form
{
return $form->schema([
TextInput::make('title')->required(),
Slug::make('slug')->fromField($title)->required(),
]);
}
Edit Workflow: Ensure the slug updates dynamically when editing existing records:
public static function editForm(Form $form): Form
{
return $form->schema([
TextInput::make('title')->required(),
Slug::make('slug')->fromField($title)->required(),
]);
}
Bulk Actions: Combine with Filament’s bulk actions to generate or update slugs for multiple records at once (requires custom logic).
Slug Collisions:
The package does not handle duplicate slugs automatically. Ensure you add a unique rule to your database column and handle collisions in your application logic (e.g., append a suffix like -2):
Slug::make('slug')
->fromField($title)
->rules(['unique:posts,slug']);
Live Updates Performance:
If the slug field is set to live(true) (default), frequent updates to the parent field (e.g., title) may cause performance issues in large forms. Consider disabling live updates for fields that don’t need real-time slug generation:
Slug::make('slug')->fromField($title)->live(false);
Conditional Logic Quirks:
The closure passed to fromField() for conditional generation must return a boolean. Ensure the logic is correct to avoid unexpected behavior:
Slug::make('slug')
->fromField($title, fn (Get $get) => !empty($get('title'))); // Example: Skip if title is empty
Database Constraints:
Always ensure your database column for the slug has a unique constraint to prevent duplicate entries. This is separate from the unique rule in the form field.
Special Characters:
The default Str::slug() may not handle all special characters as expected. Customize the slug format or use a regex rule to enforce specific patterns:
Slug::make('slug')
->fromField($title)
->regex('/^[a-z0-9\-]+$/i');
Check Field Binding:
If the slug isn’t updating, verify that the fromField() method is correctly bound to the TextInput instance:
$title = TextInput::make('title');
Slug::make('slug')->fromField($title); // Ensure $title is the correct instance
Live Updates:
If live updates aren’t working, check if live() is set to false or if there are JavaScript errors in the browser console.
Validation Errors:
Debug validation errors by checking the browser console or Filament’s error logs. Ensure rules like unique are correctly applied to the database column.
Closure Logic:
Test the closure passed to fromField() in isolation to ensure it returns the expected boolean value.
Custom Slug Generation:
Extend the package by creating a custom field that overrides the generateSlug method:
use Novius\FilamentSlug\Fields\Slug;
class CustomSlug extends Slug
{
protected function generateSlug(): string
{
return Str::slug($this->getParentFieldValue()) . '-custom';
}
}
Event Listeners: Listen for slug generation events (if the package supports them) to add custom logic:
// Example (hypothetical event)
event(new GeneratingSlug($title, $slug));
Localization:
Customize the slug generation for multilingual content by overriding the generateSlug method to handle different locales:
protected function generateSlug(): string
{
return Str::slug(app()->getLocale() === 'fr' ? $this->getParentFieldValue() : Str::lower($this->getParentFieldValue()));
}
Testing: Write unit tests for your slug fields to ensure they behave as expected in different scenarios:
public function test_slug_generation()
{
$form = YourResource::form(Form::make());
$form->fill(['title' => 'Test Title']);
$this->assertEquals('test-title', $form->get('slug'));
}
No Default Config: The package does not require a config file, but you can publish one for customization:
php artisan vendor:publish --provider="Novius\FilamentSlug\FilamentSlugServiceProvider"
Filament Version: Ensure compatibility with Filament 4.x. If upgrading Filament, test the package thoroughly for breaking changes.
PHP Version: The package requires PHP 8.2+. Ensure your environment meets this requirement to avoid runtime errors.
How can I help you explore Laravel packages today?