本文へ移動
Laravel Tips

URL を作る

アプリの中のリンクや転送先になる URL を、ヘルパー関数で作る方法を説明します。名前付きルート・署名付き URL・コントローラー・Uri クラス・初期値まで引けます。

アプリの中でリンクを書くとき、https://example.com/posts/1 のような URL を、手で全部書くこともできます。でも、ドメインや URL の形が変わると、直す場所が多くて大変です。Laravel には、URL を作るヘルパー関数(どこからでも呼べる便利な関数)がいくつかあります。テンプレートのリンク、API のレスポンス、アプリの別の場所への転送先を作るときに役に立ちます。

基本#

URL を作る#

url ヘルパー関数は、アプリの好きな URL を作ります。作られる URL は、いま処理しているリクエストの、スキーム(http か https か)とホスト(サーバーの名前)を、自動で使います。

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

echo url("/posts/{$post->id}");

// http://example.com/posts/1

クエリ文字列(URL の ? 以降の、名前=値 の並び)を付けた URL を作るなら、query メソッドを使います。

php
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

パスにすでにあるクエリ文字列と同じ名前を渡すと、もとの値が上書きされます。

php
echo url()->query('/posts?sort=latest', ['sort' => 'oldest']);

// http://example.com/posts?sort=oldest

値に配列も渡せます。値には、正しくキーが付き、エンコード(URL で使える形への変換)されます。

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

// 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

いまの URL を調べる#

url ヘルパー関数に、パスを渡さないと、Illuminate\Routing\UrlGenerator の実体が返ります。これを使うと、いまの URL の情報を調べられます。

php
// クエリ文字列を除いた、いまの URL
echo url()->current();

// クエリ文字列を含めた、いまの URL
echo url()->full();

これらのメソッドは、URL のファサード(クラス名と :: で呼べる窓口)からも呼べます。

php
use Illuminate\Support\Facades\URL;

echo URL::current();

前の URL を調べる#

いまの人が、どこから来たか、前の URL を知りたいことがあります。url ヘルパー関数の previous と previousPath で調べられます。

php
// 前のリクエストの URL(全部)
echo url()->previous();

// 前のリクエストのパス
echo url()->previousPath();

セッション(同じ人のアクセスをまたいで情報を覚えておくしくみ)からも、前の URL を、下で説明する Uri のオブジェクトとして取れます。

php
use Illuminate\Http\Request;

Route::post('/users', function (Request $request) {
    $previousUri = $request->session()->previousUri();

    // ...
});

前に見た URL のルートの名前も、セッションから取れます。

php
$previousRoute = $request->session()->previousRoute();
メソッド 説明
url パスから、アプリの URL を作る
url()->query クエリ文字列を付けた URL を作る
url()->current いまの URL(クエリ文字列なし)を返す
url()->full いまの URL(クエリ文字列あり)を返す
url()->previous 前のリクエストの URL を返す
url()->previousPath 前のリクエストのパスを返す
session()->previousUri 前の URL を、Uri のオブジェクトで返す
session()->previousRoute 前に見た URL のルートの名前を返す

名前付きルートの URL#

route ヘルパー関数は、名前付きルート(名前を付けたルート)の URL を作ります。名前を使うと、ルートに決めた本当の URL に縛られずに、URL を作れます。そのため、ルートの URL を変えても、route を呼んでいる場所は、直さなくて済みます。たとえば、次のルートがあるとします。

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

このルートの URL は、route ヘルパー関数で作ります。

php
echo route('post.show', ['post' => 1]);

// http://example.com/post/1

パラメータがいくつあるルートでも、使えます。

php
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

ルートのパラメータに当たらない、余分な配列の要素は、URL のクエリ文字列に付きます。

php
echo route('post.show', ['post' => 1, 'search' => 'rocket']);

// http://example.com/post/1?search=rocket

Eloquent のモデルを渡す#

URL を作るのに、Eloquent のモデル(データベースの表を PHP から扱いやすくしたクラス)のルートキー(ふつうは主キー。1行ずつを見分ける番号)を使うことが多いです。そこで、パラメータの値に、モデルを渡せます。route が、モデルのルートキーを、自動で取り出します。

php
echo route('post.show', ['post' => $post]);

署名付き URL#

名前付きルートに、署名(しょめい)付きの URL を作れます。署名付き URL は、クエリ文字列の最後に、署名のハッシュ(元に戻せない形に変えた文字)が付きます。Laravel は、これを見て、URL が作られたあとに、書きかえられていないかを確かめられます。だれでも開けるルートで、URL の書きかえを防ぎたいときに便利です。

たとえば、お客さんにメールで送る、だれでも開ける「配信停止」のリンクに使えます。名前付きルートの署名付き URL は、URL ファサードの signedRoute で作ります。

php
use Illuminate\Support\Facades\URL;

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

signedRoute に absolute の引数を渡すと、署名のハッシュから、ドメインを除けます。

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

決めた時間がたつと、使えなくなる、一時的な署名付き URL を作るなら、temporarySignedRoute を使います。Laravel は、一時的な署名付き URL を確かめるとき、URL に入っている期限の時刻が、すぎていないかも確かめます。

php
use Illuminate\Support\Facades\URL;

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

署名付き URL のリクエストを確かめる#

届いたリクエストの署名が正しいかは、Illuminate\Http\Request の hasValidSignature で確かめます。

php
use Illuminate\Http\Request;

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

    // ...
})->name('unsubscribe');

画面側(フロントエンド)で、署名付き URL にデータを足したいことがあります。たとえば、ページ送りをブラウザで動かすときです。そのときは、hasValidSignatureWhileIgnoring で、署名の確認で無視するクエリのパラメータを決められます。無視したパラメータは、だれでも書きかえられることに気をつけます。

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

リクエストのオブジェクトで確かめる代わりに、ルートに signed(Illuminate\Routing\Middleware\ValidateSignature)のミドルウェア(リクエストが届く前に間に入って確かめる処理)を付けられます。署名が正しくなければ、ミドルウェアが、自動で 403 の HTTP レスポンスを返します。

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

署名のハッシュに、ドメインを入れていない署名付き URL なら、ミドルウェアに relative の引数を渡します。

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

正しくない署名付き URL への答え#

期限が切れた署名付き URL を開くと、403 の HTTP ステータス用の、ふつうのエラーページが出ます。この動きは変えられます。bootstrap/app.php で、InvalidSignatureException の例外(エラーを知らせるしくみ)に、自分で書いた「render」のクロージャ(名前のない関数)を決めます。

php
use Illuminate\Routing\Exceptions\InvalidSignatureException;

->withExceptions(function (Exceptions $exceptions): void {
    $exceptions->render(function (InvalidSignatureException $e) {
        return response()->view('errors.link-expired', status: 403);
    });
})
メソッドなど 説明
URL::signedRoute 署名付き URL を作る
URL::temporarySignedRoute 期限つきの署名付き URL を作る
hasValidSignature リクエストの署名が正しいか調べる
hasValidSignatureWhileIgnoring 指定したパラメータを無視して、署名が正しいか調べる
signed ミドルウェア 署名が正しくなければ、403 を返す
signed:relative ドメインを入れない署名の場合に使う

コントローラーの動きの URL#

action 関数は、コントローラーの動き(メソッド)の URL を作ります。

php
use App\Http\Controllers\HomeController;

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

コントローラーのメソッドがルートパラメータを受け取るなら、2つ目の引数に、ルートパラメータの連想配列(名前と値の組の並び)を渡せます。

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

Uri のオブジェクト#

Laravel の Uri クラスを使うと、URI(URL のなかま)をオブジェクト(クラスから作った実体)として作ったり、変えたりできます。このクラスは、League URI というパッケージ(ほかの人が作った部品)の機能を中で使っていて、Laravel のルーティングともうまくつながります。

static メソッド(クラス名から直接呼べるメソッド)で、Uri のオブジェクトを作れます。

php
use App\Http\Controllers\UserController;
use App\Http\Controllers\InvokableController;
use Illuminate\Support\Uri;

// 渡した文字から、URI のオブジェクトを作る
$uri = Uri::of('https://example.com/path');

// パス・名前付きルート・コントローラーの動きへの、URI のオブジェクトを作る
$uri = Uri::to('/dashboard');
$uri = Uri::route('users.show', ['user' => 1]);
$uri = Uri::signedRoute('users.show', ['user' => 1]);
$uri = Uri::temporarySignedRoute('user.index', now()->plus(minutes: 5));
$uri = Uri::action([UserController::class, 'index']);
$uri = Uri::action(InvokableController::class);

// いまのリクエストの URL から、URI のオブジェクトを作る
$uri = $request->uri();

// 前のリクエストの URL から、URI のオブジェクトを作る
$uri = $request->session()->previousUri();
メソッド 説明
Uri::of 文字から、URI のオブジェクトを作る
Uri::to パスから作る
Uri::route 名前付きルートから作る
Uri::signedRoute 名前付きルートの、署名付きのものを作る
Uri::temporarySignedRoute 期限つきの署名付きのものを作る
Uri::action コントローラーの動きから作る
$request->uri いまのリクエストの URL から作る
session()->previousUri 前のリクエストの URL から作る

URI のオブジェクトを作ったら、続けて書きかえられます。

php
$uri = Uri::of('https://example.com')
    ->withScheme('http')
    ->withHost('test.com')
    ->withPort(8000)
    ->withPath('/users')
    ->withQuery(['page' => 2])
    ->withFragment('section-1');
メソッド 説明
withScheme スキーム(http か https)を変える
withHost ホストを変える
withPort ポート番号を変える
withPath パスを変える
withQuery クエリ文字列を変える
withFragment フラグメント(URL の # 以降)を変える

URI のオブジェクトの使い方は、ヘルパー関数で、くわしく説明しています。

初期値#

アプリによっては、一部の URL パラメータに、リクエスト全体で使う、初期値を決めたいことがあります。たとえば、多くのルートに、{locale}(言語の設定)のパラメータがあるとします。

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

route を呼ぶたびに、locale を渡すのは面倒です。URL::defaults メソッドで、いまのリクエストの間、いつも使われる初期値を決められます。いまのリクエストを使えるように、ルートのミドルウェアから呼ぶとよいでしょう。

php
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\URL;
use Symfony\Component\HttpFoundation\Response;

class SetDefaultLocaleForUrls
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        URL::defaults(['locale' => $request->user()->locale]);

        return $next($request);
    }
}

locale の初期値を決めたら、route で URL を作るとき、この値を渡さなくてよくなります。

URL の初期値とミドルウェアの順番#

URL の初期値を決めると、Laravel の暗黙のモデルバインディング(ルートの値から、モデルを自動で探す機能)の動きの邪魔になることがあります。そのため、URL の初期値を決めるミドルウェアは、Laravel 自身の SubstituteBindings ミドルウェアより先に動くように、順番を決めます。bootstrap/app.php の、ミドルウェアの優先を決めるメソッドで書けます。

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

関連するページ#

公式ドキュメント(英語)

2026年10月5日時点の内容をもとに、日本語でまとめています。

ページの一覧