grazulex/laravel-sharelink
Laravel ShareLink generates secure, time-limited share links for files, routes, and model previews, with password protection, rate limiting, IP filtering, one-time burn-after-reading access, and full audit trails.
Requires PHP 8.4+ — as of v1.4.0, PHP 8.3 is no longer supported. Confirm your runtime (php -v) and your CI matrix (shivammathur/setup-php with php-version: 8.4 or 8.5) before installing, and bump any Docker/dev containers still pinned to 8.3.
Install the package via Composer, publish migrations and config, then run migrations:
composer require grazulex/laravel-sharelink
php artisan vendor:publish --tag="sharelink-migrations"
php artisan vendor:publish --tag="sharelink-config"
php artisan migrate
The first use case is generating a temporary link to share a private file. For example, to share a document with a 30-minute expiration and 3 max clicks:
use Grazulex\ShareLink\Facades\ShareLink;
$link = ShareLink::create('storage/app/private/contract.pdf')
->expiresIn(30)
->maxClicks(3)
->generate();
// Send $link->url via email or embed in UI
Check config/sharelink.php to verify the default route prefix (/share) and middleware — you’ll need to route incoming share links, which the package handles automatically via its built-in controller.
File Sharing with Laravel Storage: Use disk-agnostic paths ('s3://bucket/report.pdf' or 'public://invoices/...') — the package respects Laravel’s filesystem abstraction and supports X-Sendfile/X-Accel-Redirect for optimized delivery in production.
Route-Based Sharing: Protect sensitive routes without exposing IDs:
ShareLink::create([
'type' => 'route',
'route' => 'admin.audit.show',
'parameters' => ['id' => 456]
])->expiresIn(60)->generate();
Model Previews: Enable secure preview of model data without direct access:
$link = ShareLink::create([
'type' => 'model',
'class' => User::class,
'id' => $user->id
])->expiresIn(45)->generate();
The model’s toArray() output is serialized and served as JSON upon access.
High-Security Scenarios: Combine password, IP filtering, burn-after-reading, and metadata:
ShareLink::create($sensitivePdf)
->burnAfterReading()
->withPassword('SecurePass!2025')
->metadata(['allowed_ips' => ['10.0.0.0/8']])
->maxClicks(1)
->generate();
CLI & Automation: Use Artisan commands to manage links programmatically:
php artisan sharelink:revoke abc123
php artisan sharelink:prune --days=7
Observability: Hook into events like ShareLinkAccessed, ShareLinkExpired, or ShareLinkRevoked via event listeners to integrate with logging, analytics, or alerting tools (e.g., Slack, Sentry).
PHP 8.4 Upgrade Gate: v1.4.0 is the first release dropping PHP 8.3. If you're staging multiple apps on a shared image, pin the package to ^1.3 for anything still on 8.3, or upgrade the runtime first — Composer will fail resolution rather than warn softly. Test the bump in CI before merging, and check for deprecation noise in logs after switching to 8.4/8.5.
Rector 2.x in Your Own Pipeline: The package's rector.php was updated for Rector 2.x (the removed strictBooleans prepared set was breaking vendor/bin/rector). If you run Rector over vendor/grazulex/laravel-sharelink or inherit its config, align your local Rector to 2.x — older configs referencing strictBooleans will error out.
Signed URLs are Optional: The ShareLink::signedUrl() method adds a second layer of Laravel signature validation — useful for high-stakes links but not enabled by default. Ensure your frontend doesn’t expect signed URLs unless configured via config/sharelink.php.
Burn-After-Reading ≠ First Request: Burning occurs only after successful access (i.e., correct password if required). Failed attempts (e.g., wrong password) do not consume the burn — verify in tests with dd($link->clicks).
Rate Limiting is Per-Link: Password throttling and general rate limiting apply per share link, not globally. Avoid reusing passwords across many active links — this could trigger local lockouts.
X-Sendfile Requires Server Config: To serve large files efficiently, enable x_accel_redirect or x_sendfile in both config/sharelink.php and your web server (nginx/Apache) — otherwise, the file will stream via PHP (risking memory/timeouts).
Token Safety: Tokens are UUID-based but must be treated as secrets. Never log raw tokens, and use ShareLink::uuid($token) or ShareLink::find($id) for lookups — avoid parsing URLs manually.
Metadata Column: The metadata JSON column supports custom business data (e.g., campaign ID, anonymized IP hash), but avoid storing raw PII unless encrypted at rest. Remember: it’s indexed via JSON path queries (MySQL 5.7+ / PostgreSQL) if needed later.
Testing Tip: In tests, use ShareLink::fake() to bypass DB writes and assert behaviors like URL generation or expiration logic without side effects. Combine with ->withPassword(...) and ->burnAfterReading() to verify security flows.
How can I help you explore Laravel packages today?