Weave Code
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

Laravel Sluggable Laravel Package

spatie/laravel-sluggable

Automatically generate unique, URL-friendly slugs for Laravel Eloquent models on save. Configure slug sources and target fields via a simple HasSlug trait and SlugOptions, with built-in uniqueness handling using Laravel’s Str::slug.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • SEO & URL Structure: Fits seamlessly into Laravel’s Eloquent ecosystem, enabling clean, human-readable URLs (e.g., /blog/my-article instead of /blog/123). Aligns with modern web best practices for content addressability.
  • Decoupled Logic: Slug generation is abstracted into a trait (HasSlug), adhering to the Single Responsibility Principle (SRP). Business logic (e.g., slug sources, uniqueness rules) is configurable via SlugOptions.
  • Extensibility: Supports customization via:
    • Callables for dynamic slug generation.
    • Scopes for multi-tenant or hierarchical slugs (e.g., scope_id).
    • Language/locale-specific slugs (via laravel-translatable integration).
  • Performance: Generates slugs on save, avoiding runtime overhead during queries. Uses Laravel’s built-in Str::slug for efficiency.

Integration Feasibility

  • Laravel Native: Zero external dependencies beyond Laravel core (uses Str::slug, Eloquent events). No conflicts with existing Laravel features (e.g., implicit model binding).
  • Database Agnostic: Works with any Laravel-supported database (MySQL, PostgreSQL, SQLite). Requires a slug column (e.g., string(255)), which is trivial to add.
  • Event-Driven: Hooks into Eloquent’s saving event, ensuring atomicity (slug generation fails if model save fails).
  • Backward Compatibility: Non-breaking changes (e.g., new SlugOptions methods) are additive. Existing implementations remain functional.

Technical Risk

Risk Area Assessment Mitigation
Slug Collisions Default behavior appends -N to duplicates, but custom suffixes may fail. Use usingSuffixGenerator for deterministic uniqueness (e.g., UUIDs).
Migration Complexity Requires adding a slug column to existing tables. Scripted migration with downtime planning (if applicable).
Locale/Translation Overhead HasTranslatableSlug adds complexity for multi-lingual apps. Test thoroughly with laravel-translatable; consider caching slugs.
Route Binding Conflicts Custom getRouteKeyName() may clash with existing routes. Validate slug uniqueness in route constraints (e.g., where('slug', '[a-z0-9\-]+')).
Performance at Scale High write volume could stress slug uniqueness checks. Benchmark with allowDuplicateSlugs() for read-heavy workloads.

Key Questions

  1. Slug Uniqueness Requirements:
    • Are duplicate slugs acceptable (e.g., for drafts)? If not, how should conflicts be resolved (e.g., manual review vs. auto-increment)?
  2. Route Integration:
    • Will slugs replace numeric IDs in all routes? If partial, how will conflicts with existing routes be handled?
  3. Multi-Lingual Support:
    • Is laravel-translatable integration needed? If so, are there performance concerns for large datasets?
  4. Existing Data:
    • How will slugs be backfilled for existing records? (Manual? Batch job?)
  5. Customization Needs:
    • Are there non-standard slug formats (e.g., UUIDs, hashes) that require usingSuffixGenerator?
  6. Testing Strategy:
    • Should slug generation be mocked in unit tests? How will edge cases (e.g., special characters) be handled?

Integration Approach

Stack Fit

  • Laravel Ecosystem: Native support for Eloquent, routes, and Str helpers. No framework-specific limitations.
  • Database: Compatible with all Laravel-supported databases. JSON fields are unsupported for slug storage (use string).
  • Caching: Slugs are generated on save; consider caching for read-heavy apps (e.g., Redis for findBySlug).
  • Queue Jobs: For large migrations, slug generation can be deferred using Laravel Queues (e.g., Model::dispatchSync()).

Migration Path

  1. Phase 1: Pilot Model

    • Add slug column to a non-critical model (e.g., BlogPost).
    • Implement HasSlug trait and test slug generation/route binding.
    • Validate performance impact (e.g., tinker tests for 10K inserts).
  2. Phase 2: Core Models

    • Roll out to high-priority models (e.g., Product, Article).
    • Update routes to use slugs (e.g., Route::get('/posts/{post:slug}', ...)).
    • Backfill slugs for existing records via a queue job.
  3. Phase 3: Full Adoption

    • Replace numeric IDs in all public routes with slugs.
    • Deprecate old routes (e.g., /posts/123) via middleware redirects.

Compatibility

  • Laravel Versions: Tested with Laravel 8+ (check composer.json for min version).
  • PHP Versions: Requires PHP 8.0+ (due to named arguments in SlugOptions).
  • Package Conflicts: None identified. Avoids global helpers or service providers.
  • Custom Validation: Extend SlugOptions for app-specific rules (e.g., regex patterns).

Sequencing

  1. Database Schema:
    • Add slug column to all target tables (use a migration factory for consistency).
    Schema::table('posts', function (Blueprint $table) {
        $table->string('slug')->unique()->after('title');
    });
    
  2. Model Integration:
    • Add HasSlug trait and getSlugOptions() to models.
    • Set getRouteKeyName('slug') for implicit binding.
  3. Route Updates:
    • Replace {id} with {model:slug} in route definitions.
    • Add route constraints (e.g., where('slug', '[\w\-]+')).
  4. Testing:
    • Unit tests for slug generation (edge cases: Unicode, special chars).
    • Integration tests for route binding and findBySlug.
  5. Deployment:
    • Feature flag slug routes during rollout (e.g., config('app.use_slug_routes')).
    • Monitor slug collision rates post-launch.

Operational Impact

Maintenance

  • Long-Term Costs:
    • Low operational overhead (slugs are generated once per save).
    • No cron jobs or external services required.
  • Deprecation:
    • Slugs are immutable by default (unless preventOverwrite() is disabled). Plan for:
      • Manual slug updates via admin panels.
      • Batch updates for renamed content (e.g., Post::where('title', 'old-name')->update(['slug' => Str::slug('new-name')])).
  • Documentation:
    • Update API docs to reflect slug-based routes.
    • Add internal notes on slug generation rules (e.g., "Slugs for Product use name + category").

Support

  • Common Issues:
    • Duplicate Slugs: Log warnings for collisions (extend SlugOptions to emit events).
    • Route Errors: Ensure getRouteKeyName() is consistent across models.
    • Unicode Handling: Test with non-ASCII characters (e.g., Str::slug('café')cafe).
  • Debugging:
    • Add a generateSlug() method to models for manual testing.
    • Log slug generation failures (e.g., try-catch in HasSlug trait).

Scaling

  • Write Performance:
    • Slug uniqueness checks add ~5–10ms per save (benchmark with DB::enableQueryLog()).
    • For high-volume apps, consider:
      • Database indexes on slug columns.
      • Caching slugs in Redis (e.g., cache()->remember("slug:{$model->id}", ...)).
  • Read Performance:
    • findBySlug is O(1) with proper indexing. No scaling concerns.
  • Multi-Region Deployments:
    • Slugs are stateless; no synchronization needed across regions.

Failure Modes

Failure Scenario Impact Mitigation
Database connection failure Slugs not generated/saved. Retry logic in HasSlug trait (e.g., save() with exponential backoff).
Slug collision rate > 1% Performance degradation. Monitor via DB::listen(); alert on high collision counts.
Route binding mismatch 404 errors for valid slugs. Validate getRouteKeyName() in tests; use Route::bind() as fallback.
Custom suffix generator fails Duplicate slugs. Fallback to default -N suffix (e.g., try-catch in usingSuffixGenerator).
Migration backfill errors
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport