vlados/laravel-unique-urls
Laravel package for generating and managing unique URLs, helping you create collision-free slugs and SEO-friendly permalinks for models and content with automatic uniqueness checks and customizable URL patterns.
app/ layout — v2.2.0 makes urls:generate and urls:doctor module-aware out of the box (nwidart/laravel-modules layouts plus the legacy Models/Entities conventions, or an explicit model_paths map). Adopting a module structure is no longer a silent regression for URL coverage.urls:doctor --strict turns empty or partial scans into a non-zero exit code, making "every model has a reachable, unique URL" a CI-enforceable invariant rather than a manual QA checklist item.App\Models and Modules\* now keep working via bare-name fallback in --model; ambiguous short names fail loudly with candidates listed instead of resolving arbitrarily. This de-risks the "extract a module" roadmap item.Consider adoption when:
--strict) rather than a post-deploy discovery.urlHandler() controller resolved through Laravel's ControllerResolver (Livewire __invoke() style, or a declared method with show()/index() fallbacks) and a urlStrategy() for slug derivation.Look elsewhere when:
ControllerResolver).urlStrategy() throwing to signal problems — failures there are deliberately silent, so anything you need alerted on must be surfaced through another layer.For executives: This release hardens the layer that decides what URL every record in the product gets. The material business value is twofold: SEO and link integrity (unique, resolvable URLs per model) and reduced release risk — URL coverage is now checkable in CI, and a clean run reports exactly how many models across how many paths were verified instead of a bare "Everything is ok." The upgrade is non-breaking: no configuration change is required, and the new scan is a superset of the old app/-only behaviour.
For engineering: v2.2.0 fixes three real defects rather than adding surface area. (1) ModelDiscoveryService resolves scan directories alongside their PSR-4 root and namespace prefix, defaulting to app/ plus configured module paths, with a new model_paths key that accepts a bare directory, a Namespace => /directory pair, or a full path/base_path/namespace descriptor — non-existent directories are skipped. (2) urls:doctor now distinguishes "clean" from "nothing checked": it names any path yielding zero models, warns when the whole scan is empty, and --strict converts either condition into a CI failure. (3) --model is now uniform across both commands — fully qualified names work, bare names resolve against App\Models then fall back to discovered models, ambiguity is reported with candidates, and missing classes are errors rather than container exceptions. Handler validation now mirrors request-time resolution via ControllerResolver (including __invoke(), show()/index() fallbacks and Livewire component names), and trait detection uses class_uses_recursive() so inherited usage is covered.
Expectation to set before upgrading: projects that have already moved models into modules should anticipate urls:doctor reporting more findings than before. That is the previous blind spot becoming visible, not a regression — budget a short remediation pass, then enable --strict in CI to keep it closed.
How can I help you explore Laravel packages today?