Weave 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

Generate unique slugs for Eloquent models on create or update via a Sluggable attribute or HasSlug trait. Includes collision suffixes, translatable slugs, and self-healing URLs with 308 redirects.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • Narrowly scoped, single-responsibility utility: takes a source attribute (or closure) and materializes a unique slug on saving. It is a convenience layer over Str::slug() plus a uniqueness loop — not a content-addressing or routing framework. Fit is high for any Laravel app with public-facing, human-readable URLs (posts, pages, categories, products, tags).
  • Two integration APIs coexist in v4: a #[Sluggable] PHP attribute (declarative, no closures) and the HasSlug trait with getSlugOptions() (needed for scoped uniqueness, conditional skip, custom suffix generators). This is a governance decision, not a technical one — pick one per codebase or expect drift.
  • The self-healing URL feature is materially different in scope from slug generation: it overrides Eloquent's getRouteKeyName/resolveRouteBinding and emits 308 redirects. That touches routing, caching, and SEO — treat it as a separate approval, not a bundled freebie.

Integration feasibility

  • Trivial install (composer require), no service, no migration generator, no config publish required for the basic path. A competent Laravel developer can pilot on one model in under a day.
  • Backfill of existing rows is the only real work: add nullable slug, backfill via chunked job or artisan command, dedupe, then add a unique index. That migration sequence must be explicit — adding the unique index before backfill will fail on large tables.
  • Attribute-only models get slugs but not self-healing URLs; the trait is still required for route-key overrides. This is the most likely silent misconfiguration and should be a code-review checkpoint.

Technical risk

  • Uniqueness is application-level, not database-level. The package does a read-then-write suffix lookup (-1, -2, …). Under concurrent writes two requests can compute the same slug. A database unique index plus retry-on-conflict is mandatory; without it this becomes a data-integrity incident, not a bug report.
  • Driver-sensitive suffix logic. Changelog 4.0.3 fixes LIKE wildcard handling (_, %, \) that silently reused suffixes on SQLite. Any org on multiple engines (SQLite in tests, Postgres/MySQL in prod) should test separator choices and confirm parity.
  • Version gate. v4 requires PHP 8.3 and Laravel 12. L10/L11 or PHP 8.1/8.2 estates are blocked on v3.x and will diverge from the maintained line. Validate the v3.8 support matrix (it claims Laravel 13 / PHP 8.5) before pinning.
  • Route-key override blast radius. HasSlug replaces Eloquent binding methods globally for the model. Interactions with nested/child bindings, policies, and any other package overriding the same methods need review. Self-healing parsing assumes the primary key is recoverable from the URL segment — non-integer or UUID keys are a design constraint to verify.
  • Ecosystem signal is noisy. The "0 dependents" figure is almost certainly a data-capture artifact for a package with this download profile; do not use it as an ecosystem-risk verdict. Conversely, low score (43.5) mostly reflects scope size, not quality.

Key questions

  • Which entities are in scope, and are their URLs SEO-relevant or purely internal?
  • Are slugs immutable after publish? What is the policy when a title changes — regenerate (link churn) or freeze (stale-but-stable)?
  • Do we need localized slugs, and is spatie/laravel-translatable v6+ already in the stack?
  • Do we own a canonical-URL and redirect-map strategy, and do CDN/analytics handle 308 correctly (including counting it as a redirect, not a 200)?
  • What is the primary key type on affected tables — integer, UUID, ULID?
  • Do batch imports, upsert, or raw query builders touch these tables? Those bypass model events and will silently produce NULL slugs.

Integration Approach

Stack fit

  • Native Laravel/PHP; no infrastructure footprint, no runtime dependency beyond illuminate/*. Optional second package only if translatable slugs are in scope.
  • Best value where URL stability has commercial weight: content marketing, SEO landing pages, public documentation, catalog permalinks. Low value for internal admin models — don't spend adoption budget there.

Migration path

  • Phase 0: inventory existing slug logic (Str::slug calls, model accessors, route model binding overrides) and consolidate before adopting, otherwise two competing mechanisms will produce inconsistent URLs.
  • Phase 1: schema — nullable slug column, index after backfill, then unique constraint. Ship a deterministic backfill command that is idempotent and reports collisions.
  • Phase 2: enable #[Sluggable] on one model; keep self-healing off.
  • Phase 3: enable self-healing (HasSlug + selfHealing: true) only on models where external links exist and 308 semantics are acceptable.
  • Phase 4: translatable slugs, gated on the localization roadmap — not a launch dependency.

Compatibility

  • v4 mandates Laravel 12 / PHP 8.3; also upgrades Pest 4 / Testbench 10 in your suite. Budget test-harness churn, not just package churn.
  • v4 breaking changes to watch if upgrading from v3: skipGenerateWhen() now evaluated on every save, closure-only typing for option callbacks, removal of the $slugOptions cache, Sluggable facade renamed to SelfHealing, redirect default changed 301 → 308.
  • 4.x point releases are still finding correctness bugs in uniqueness logic (4.0.3). Pin to a patch range and subscribe to releases rather than floating.

Sequencing

  • Cheapest first: single low-traffic model → observe → expand. Self-healing and translatability are independent feature flags; land them in separate releases so a regression in one doesn't roll back the other.
  • Ship the unique index and the concurrency-retry story in the same release as the first slug column. Never ship slugs without the constraint.

Operational Impact

Maintenance

  • Effectively zero standing maintenance: no daemon, no scheduled job, no config surface in the basic path. Upgrades are Composer bumps with occasional test-harness fallout at majors.
  • Lock-in is minimal — the abstraction is thin enough to inline (Str::slug + uniqueness query) in a day if the package is ever abandoned. That caps long-term risk regardless of maintainer health.
  • Ongoing cost is policy cost, not code cost: someone must own the "do slugs change?" rule and the redirect map.

Support

  • Maintained by Spatie with a documented changelog, upgrade guide, and release cadence. Bus factor concentrates on the agency's core maintainers; acceptable given the small surface, but avoid becoming the org's only consumer of an exotic fork.
  • The bundled Laravel Boost skill is a genuine ramp-up accelerator for AI-assisted scaffolding, with a caveat: generated code using the attribute alone will omit self-healing unless the trait is also added. Encode that in the scaffolding template, not in tribal knowledge.

Scaling

  • Cost is one extra SELECT per save for the uniqueness check. Negligible for interactive writes; material for large imports. Route bulk ingestion through chunked jobs that respect model events, or generate slugs in a post-import pass.
  • Self-healing adds a redirect hop on stale URLs — cache at the edge and monitor hit rates; a poorly cached redirect layer on high-traffic content is a measurable latency line item.
  • Slug length and transliteration are silent scale risks: long CJK or accented titles can exceed column width or collapse to near-empty slugs. Validate and enforce a max length plus a deterministic fallback.

Failure modes

  • Duplicate slugs under concurrent writes (no DB constraint) → routing ambiguity, wrong record resolves.
  • NULL slugs from insert()/upsert()/seeders/mass updates that bypass Eloquent events → 404s discovered in production.
  • Slug churn on rename breaking external backlinks if self-healing is off.
  • Self-healing parser mismatch on UUID/non-integer keys → redirect loop or unresolvable binding.
  • Driver-specific uniqueness bugs (per 4.0.3) surfacing only in the SQLite test suite or only in production, depending on which engine you test against.
  • Over-broad trait adoption overriding route keys on models where it was never intended.

Ramp-up

  • Hours to first value for a Laravel-comfortable developer; the README's two-line example is genuinely sufficient. Docs site covers the closure-based options.
  • Recommend a one-page internal standard: which API (attribute vs trait), column conventions, index requirement, rename policy, self-healing opt-in criteria, and a PR checklist item for event-bypassing writes. That artifact is the actual deliverable — the package itself is commodity.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package