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 Short Url Laravel Package

jeffersongoncalves/laravel-short-url

Laravel Short URL is a package for creating and managing short links in Laravel applications. Generate compact URLs, customize aliases, and handle redirects through a simple, framework-friendly API so you can add short-link functionality quickly. Ideal for campaigns, dashboards, and internal tools.

View on GitHub
Deep Wiki
Context7

Getting Started

The package registers short-URL routes for you; there is very little setup before you can redirect a slug.

  1. Install and publish config: composer require <vendor>/<package> then php artisan vendor:publish --tag=short-url-config (or the package's config tag). Check the published config/short-url.php first — particularly the route block.
  2. Run the migration if the package stores URLs in the database (php artisan migrate), then create your first URL:
    use AshAllenDesign\ShortURL\Facades\ShortURL; // or the package's facade/helper
    
    $shortURL = ShortURL::destinationUrl('https://example.com/some/long/path')->make();
    echo $shortURL->default_short_url;
    
  3. Hit the returned short URL in a browser. If it 404s, verify short-url.route.fallback is enabled and that APP_URL / the route prefix match what you're requesting. Note that with the fallback enabled, any unmatched path — including GET / on an app with no root route — is now answered by the fallback, so a stray 404 on / is expected behaviour rather than a broken install (5.2.4).

First use case for most apps: generating shareable links from a controller (invite links, campaign URLs, signed download links). Confirm the destination_url is normalized as you expect before you wire it into anything user-facing.

Implementation Patterns

Redirect-only vs. tracked URLs. For throwaway links, the minimal destinationUrl(...)->make() call is enough. For anything you want to measure, add tracking options before make() (->trackVisits(), ->trackIPAddress(), ->trackDeviceType() etc.) — these are typically opt-in at creation time, so decide per link rather than globally.

Key-based lookup in your own controllers. The package is usually paired with a route that resolves a slug. Wrap resolution in a try/catch for the package's "not found" exception and translate it into a 404 of your own, so behaviour is consistent with the rest of your app:

try {
    $url = ShortURL::findByKey($key);
} catch (\Throwable $e) {
    abort(404);
}
return redirect()->away($url->destination_url, $url->redirect_status_code ?? 302);

Middleware and fallback route precedence (5.2.3–5.2.4 behaviour). The fallback route is deliberately outside the web middleware group. Host-app routes always win because they are registered first; the fallback only catches what is left over. That means:

  • Your own Route::post('/short/{key}') still runs full web middleware, including CSRF — good, keep it if you need authenticated or validated behaviour.
  • Unmatched POST/PUT/PATCH/DELETE traffic to the short-url prefix returns 404, not 405.
  • As of 5.2.4, the same applies to QUERY requests (404 instead of 405) and to non-GET requests on the root path (POST / now returns 404 rather than throwing a TypeError → 500). If you previously relied on 405 responses to detect misconfigured clients, or on a 500 on POST / as a smoke signal that something was routing oddly, both signals are gone.
  • Because the fallback skips web middleware, it will never fire CSRF 419s for unmatched verbs. If you had a workaround middleware or a VerifyCsrfToken::$except entry added solely to silence 419s on the short-url prefix, remove it and retest.

Route registration order. In RouteServiceProvider, register the package's routes after your application routes if you want your routes to take precedence in edge cases. Most projects don't need this, but it matters when you mount your own handlers under the same prefix. It also matters if you do have a GET / route: registering your root route normally keeps it winning over the fallback.

Environment parity. Keep short-url.route.fallback on in local and staging as well as production, otherwise the 404-vs-405 behaviour, the root-path handling, and any client behaviour that depends on it will only surface in production.

Gotchas and Tips

Unmatched traffic now uniformly yields 404 — including the root path. 5.2.3 changed non-GET requests on the short-url prefix from 405 to 404; 5.2.4 extends that to QUERY requests and fixes a TypeError/500 that POST / (and other non-GET root requests) raised when the fallback was enabled. Audit any client, API consumer, monitoring probe, or test suite that asserts on status codes for the short-url prefix or for /:

  • ->post('/s/abc')->assertStatus(405) must become assertNotFound().
  • A test asserting POST / returns 500 (or any 4xx other than 404) must become assertNotFound().
  • Anything that treated POST / 500s as an uptime alert now needs a different signal, or it will silently pass.

Fallback + CSRF is the important safety win. Any request that reaches the fallback is answered without the web middleware, so CSRF can't intercept it. If you have custom middleware in the web group that mutates responses globally (e.g. security headers, locale switching), it will not apply to fallback-served redirects — nor to fallback-served 404s. Register any truly global headers as terminable/global middleware if you need them on short-URL responses too.

Root-route collisions. Now that the fallback reliably claims / for non-GET verbs (and for GET / when you have no root route), be explicit about intent: if you want POST / handled by your app, define that route in your app (it wins by registration order); if you expect a 404, you'll get the fallback's 404. Don't rely on the previous 500 as a canary.

Host routes keep precedence — but only if registered first. If a route in your app is not matching and you're getting a package redirect instead, the cause is almost always registration order or a prefix collision, not the fallback logic. Check php artisan route:list --path=your-prefix (and --path=/ for the root case) to see the resolved order.

Status codes are per-URL data, not config. The redirect status (302 vs 301) lives on the short URL record. Changing a default in config does not rewrite existing rows; write a one-off migration/console command if you need to bulk-change. 301s are cached aggressively by browsers — avoid them for anything you might need to revoke.

Debugging missed redirects. Three usual suspects, in order: (1) the key column doesn't match the URL you're requesting (case-sensitivity or extra path segments); (2) the URL is deactivated (activated_at, deactivated_at) and the package is silently treating it as not-found; (3) fallback is disabled and no route exists for the prefix. Log the resolved key and the lookup result rather than the whole model. A 404 that "used to be a 405/500" is almost always the fallback doing its job, not a regression.

Extension points worth knowing. The destination URL builder and the visit model are typically swappable via config; if you need custom tracking dimensions, prefer extending the visit model and adding a custom builder method over forking the package. Also confirm the package's migrations are published — running them from the vendor directory works until you need to alter a column.

Rate limiting. The fallback route is unauthenticated by nature and now also answers root-path traffic. If the prefix is guessable, add a throttle middleware to a host-defined fallback route that calls into the package, or accept that slug enumeration is possible and make slugs long/random.

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.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums