open-southeners/laravel-model-permalink
Laravel package that generates permanent, shareable links for Eloquent models. Create stable permalink URLs for any record with configurable routes and slugs, so entries stay reachable as their content or IDs change.
composer require opensoutheners/laravel-model-permalink, then publish and run the migration so the permalinks table exists (php artisan vendor:publish --tag="model-permalink-migrations" and php artisan migrate). Publish the config file as well if you need to change the route prefix, middleware, or redirect behaviour.config/model-permalink.php (route registration/prefix/middleware), the HasPermalinks trait, and the package's own controller — that controller is the code path that resolves an incoming permalink and redirects to the model, and it is now also the source of the new PermalinkGotAccessed event.use OpenSoutheners\LaravelModelPermalink\Concerns\HasPermalinks;
class Invoice extends Model
{
use HasPermalinks;
}
use OpenSoutheners\LaravelModelPermalink\Events\PermalinkGotAccessed;
Event::listen(function (PermalinkGotAccessed $event) {
// $event->permalink (and/or the related model) — inspect the class for the exact payload
AccessLog::create([...]);
});
created model event or an observer so every record is shareable regardless of which entry point created it. Controllers stay thin and you avoid the "some rows have no permalink" data drift.PermalinkGotAccessed is the clean integration point for analytics: store hits, increment counters, feed a dashboard, or dispatch a queued job. Keep the listener fast and ShouldQueue any I/O so a slow analytics write never delays the redirect.auth, signed, rate limiting) via the published config so the package route inherits it. This keeps the redirect path consistent for every model type.Event::fake([PermalinkGotAccessed::class]) plus Event::assertDispatched to verify your tracking wiring independently of the redirect assertion.PermalinkGotAccessed. If you need guaranteed coverage, either funnel all access through the package route or add your own explicit event dispatch at the other entry points; don't assume the listener sees everything.src/Events/PermalinkGotAccessed.php. Newly added events often get refined in the next minor, so wrap access in your listener and keep the listener thin./. Use a distinct prefix (e.g. /p/{permalink}) or verify route order; a permalink that collides with a real path silently shadows it.php artisan route:list --path=<prefix> confirms the package route is actually registered.How can I help you explore Laravel packages today?