Mastering Laravel URL Generation

aravel Laravel Views & Blade Templates – Beginner’s Guide

Laravel URL Generation Tutorial

Laravel provides several helpers and facades to generate URLs dynamically. Instead of hardcoding URLs in your application, you can use these helpers to create links that automatically adapt when your routes, parameters, or environment change.

This is essential for:

  • Building links in Blade templates.
  • Returning URLs in API responses.
  • Creating redirects dynamically.

The Basics of URL Generation

Generating URLs with url()

The url() helper is the simplest way to generate a URL:

$post = App\Models\Post::find(1);

echo url("/posts/{$post->id}");
// Output: http://example.com/posts/1

🔹 Laravel automatically detects your current scheme (http or https) and host.


Adding Query Parameters

Use url()->query() to add query strings:

echo url()->query('/posts', ['search' => 'Laravel']);
// https://example.com/posts?search=Laravel

echo url()->query('/posts?sort=latest', ['search' => 'Laravel']);
// http://example.com/posts?sort=latest&search=Laravel

If the query parameter already exists, Laravel overwrites it:

echo url()->query('/posts?sort=latest', ['sort' => 'oldest']);
// http://example.com/posts?sort=oldest

✅ Arrays are also supported:

$url = url()->query('/posts', ['columns' => ['title', 'body']]);

echo $url;
// http://example.com/posts?columns%5B0%5D=title&columns%5B1%5D=body

echo urldecode($url);
// http://example.com/posts?columns[0]=title&columns[1]=body

Accessing Current, Full, and Previous URLs

// Current URL without query string
echo url()->current();

// Current URL with query string
echo url()->full();

// Previous full URL
echo url()->previous();

// Previous request path only
echo url()->previousPath();

Alternatively, use the URL facade:

use Illuminate\Support\Facades\URL;

echo URL::current();

URLs for Named Routes

Why Use Named Routes?

Hardcoding URLs is error-prone. If the route changes, you must update it everywhere. Instead, use named routes.

Route::get('/post/{post}', function (Post $post) {
    // ...
})->name('post.show');

Now you can generate the URL with:

echo route('post.show', ['post' => 1]);
// http://example.com/post/1

Routes with Multiple Parameters

Route::get('/post/{post}/comment/{comment}', function (Post $post, Comment $comment) {
    // ...
})->name('comment.show');

echo route('comment.show', ['post' => 1, 'comment' => 3]);
// http://example.com/post/1/comment/3
Extra Query Parameters

Any extra array items become query strings:

echo route('post.show', ['post' => 1, 'search' => 'rocket']);
// http://example.com/post/1?search=rocket

Passing Eloquent Models

The route() helper automatically extracts the route key from models:

echo route('post.show', ['post' => $post]);
// http://example.com/post/1

Signed URLs

Signed URLs prevent tampering with query strings by appending a hash.

Generating a Signed URL
use Illuminate\Support\Facades\URL;

return URL::signedRoute('unsubscribe', ['user' => 1]);

Exclude domain from hash:

URL::signedRoute('unsubscribe', ['user' => 1], absolute: false);
Temporary Signed URL

Expire the link after a time limit:

return URL::temporarySignedRoute(
    'unsubscribe',
    now()->addMinutes(30),
    ['user' => 1]
);

Validating Signed Requests

use Illuminate\Http\Request;

Route::get('/unsubscribe/{user}', function (Request $request) {
    if (! $request->hasValidSignature()) {
        abort(401);
    }
});

Allow certain query params to be ignored:

if (! $request->hasValidSignatureWhileIgnoring(['page', 'order'])) {
    abort(401);
}

Using Middleware for Validation

Instead of checking manually:

Route::post('/unsubscribe/{user}', function () {
    // ...
})->name('unsubscribe')->middleware('signed');

If using relative signed URLs:

->middleware('signed:relative');

Handling Expired Links

Customize error for invalid signature:

use Illuminate\Routing\Exceptions\InvalidSignatureException;

->withExceptions(function ($exceptions) {
    $exceptions->render(function (InvalidSignatureException $e) {
        return response()->view('errors.link-expired', status: 403);
    });
});

URLs for Controller Actions

Use action() for controller routes:

use App\Http\Controllers\HomeController;

$url = action([HomeController::class, 'index']);

With parameters:

$url = action([UserController::class, 'profile'], ['id' => 1]);

Fluent URI Objects

Laravel’s Uri class provides an object-based approach to build and modify URLs.

Creating URIs
use Illuminate\Support\Uri;

// From a string
$uri = Uri::of('https://example.com/path');

// From Laravel helpers
$uri = Uri::to('/dashboard');
$uri = Uri::route('users.show', ['user' => 1]);
$uri = Uri::signedRoute('users.show', ['user' => 1]);
$uri = Uri::temporarySignedRoute('user.index', now()->addMinutes(5));
$uri = Uri::action([UserController::class, 'index']);
Modifying URIs
$uri = Uri::of('https://example.com')
    ->withScheme('http')
    ->withHost('test.com')
    ->withPort(8000)
    ->withPath('/users')
    ->withQuery(['page' => 2])
    ->withFragment('section-1');

Default URL Parameters

You can set default values for URL parameters across a request.

Example: Default locale
Route::get('/{locale}/posts', function () {
    // ...
})->name('post.index');

Define defaults in a middleware:

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\URL;

class SetDefaultLocaleForUrls
{
    public function handle($request, Closure $next)
    {
        URL::defaults(['locale' => $request->user()->locale]);
        return $next($request);
    }
}

Now you don’t need to pass locale every time.


Middleware Priority

Because default values can conflict with model binding, ensure this middleware runs before SubstituteBindings:

->withMiddleware(function ($middleware) {
    $middleware->prependToPriorityList(
        before: \Illuminate\Routing\Middleware\SubstituteBindings::class,
        prepend: \App\Http\Middleware\SetDefaultLocaleForUrls::class,
    );
});

Important

Laravel provides flexible URL generation helpers that make your app more dynamic and maintainable.

  • Use url() for simple paths and queries.
  • Use route() for named routes (best practice).
  • Use signed URLs for security.
  • Use action() for controller links.
  • Use Uri for object-oriented URL building.
  • Use URL::defaults() to define global parameters.