URL を作る
アプリの中のリンクや転送先になる URL を、ヘルパー関数で作る方法を説明します。名前付きルート・署名付き URL・コントローラー・Uri クラス・初期値まで引けます。
アプリの中でリンクを書くとき、https://example.com/posts/1 のような URL を、手で全部書くこともできます。でも、ドメインや URL の形が変わると、直す場所が多くて大変です。Laravel には、URL を作るヘルパー関数(どこからでも呼べる便利な関数)がいくつかあります。テンプレートのリンク、API のレスポンス、アプリの別の場所への転送先を作るときに役に立ちます。
基本#
URL を作る#
url ヘルパー関数は、アプリの好きな URL を作ります。作られる URL は、いま処理しているリクエストの、スキーム(http か https か)とホスト(サーバーの名前)を、自動で使います。
$post = App\Models\Post::find(1);
echo url("/posts/{$post->id}");
// http://example.com/posts/1
クエリ文字列(URL の ? 以降の、名前=値 の並び)を付けた URL を作るなら、query メソッドを使います。
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
パスにすでにあるクエリ文字列と同じ名前を渡すと、もとの値が上書きされます。
echo url()->query('/posts?sort=latest', ['sort' => 'oldest']);
// http://example.com/posts?sort=oldest
値に配列も渡せます。値には、正しくキーが付き、エンコード(URL で使える形への変換)されます。
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 の情報を調べられます。
// クエリ文字列を除いた、いまの URL
echo url()->current();
// クエリ文字列を含めた、いまの URL
echo url()->full();
これらのメソッドは、URL のファサード(クラス名と :: で呼べる窓口)からも呼べます。
use Illuminate\Support\Facades\URL;
echo URL::current();
前の URL を調べる#
いまの人が、どこから来たか、前の URL を知りたいことがあります。url ヘルパー関数の previous と previousPath で調べられます。
// 前のリクエストの URL(全部)
echo url()->previous();
// 前のリクエストのパス
echo url()->previousPath();
セッション(同じ人のアクセスをまたいで情報を覚えておくしくみ)からも、前の URL を、下で説明する Uri のオブジェクトとして取れます。
use Illuminate\Http\Request;
Route::post('/users', function (Request $request) {
$previousUri = $request->session()->previousUri();
// ...
});
前に見た URL のルートの名前も、セッションから取れます。
$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 を呼んでいる場所は、直さなくて済みます。たとえば、次のルートがあるとします。
Route::get('/post/{post}', function (Post $post) {
// ...
})->name('post.show');
このルートの URL は、route ヘルパー関数で作ります。
echo route('post.show', ['post' => 1]);
// http://example.com/post/1
パラメータがいくつあるルートでも、使えます。
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 のクエリ文字列に付きます。
echo route('post.show', ['post' => 1, 'search' => 'rocket']);
// http://example.com/post/1?search=rocket
Eloquent のモデルを渡す#
URL を作るのに、Eloquent のモデル(データベースの表を PHP から扱いやすくしたクラス)のルートキー(ふつうは主キー。1行ずつを見分ける番号)を使うことが多いです。そこで、パラメータの値に、モデルを渡せます。route が、モデルのルートキーを、自動で取り出します。
echo route('post.show', ['post' => $post]);
署名付き URL#
名前付きルートに、署名(しょめい)付きの URL を作れます。署名付き URL は、クエリ文字列の最後に、署名のハッシュ(元に戻せない形に変えた文字)が付きます。Laravel は、これを見て、URL が作られたあとに、書きかえられていないかを確かめられます。だれでも開けるルートで、URL の書きかえを防ぎたいときに便利です。
たとえば、お客さんにメールで送る、だれでも開ける「配信停止」のリンクに使えます。名前付きルートの署名付き URL は、URL ファサードの signedRoute で作ります。
use Illuminate\Support\Facades\URL;
return URL::signedRoute('unsubscribe', ['user' => 1]);
signedRoute に absolute の引数を渡すと、署名のハッシュから、ドメインを除けます。
return URL::signedRoute('unsubscribe', ['user' => 1], absolute: false);
決めた時間がたつと、使えなくなる、一時的な署名付き URL を作るなら、temporarySignedRoute を使います。Laravel は、一時的な署名付き URL を確かめるとき、URL に入っている期限の時刻が、すぎていないかも確かめます。
use Illuminate\Support\Facades\URL;
return URL::temporarySignedRoute(
'unsubscribe', now()->plus(minutes: 30), ['user' => 1]
);
署名付き URL のリクエストを確かめる#
届いたリクエストの署名が正しいかは、Illuminate\Http\Request の hasValidSignature で確かめます。
use Illuminate\Http\Request;
Route::get('/unsubscribe/{user}', function (Request $request) {
if (! $request->hasValidSignature()) {
abort(401);
}
// ...
})->name('unsubscribe');
画面側(フロントエンド)で、署名付き URL にデータを足したいことがあります。たとえば、ページ送りをブラウザで動かすときです。そのときは、hasValidSignatureWhileIgnoring で、署名の確認で無視するクエリのパラメータを決められます。無視したパラメータは、だれでも書きかえられることに気をつけます。
if (! $request->hasValidSignatureWhileIgnoring(['page', 'order'])) {
abort(401);
}
リクエストのオブジェクトで確かめる代わりに、ルートに signed(Illuminate\Routing\Middleware\ValidateSignature)のミドルウェア(リクエストが届く前に間に入って確かめる処理)を付けられます。署名が正しくなければ、ミドルウェアが、自動で 403 の HTTP レスポンスを返します。
Route::post('/unsubscribe/{user}', function (Request $request) {
// ...
})->name('unsubscribe')->middleware('signed');
署名のハッシュに、ドメインを入れていない署名付き URL なら、ミドルウェアに relative の引数を渡します。
Route::post('/unsubscribe/{user}', function (Request $request) {
// ...
})->name('unsubscribe')->middleware('signed:relative');
正しくない署名付き URL への答え#
期限が切れた署名付き URL を開くと、403 の HTTP ステータス用の、ふつうのエラーページが出ます。この動きは変えられます。bootstrap/app.php で、InvalidSignatureException の例外(エラーを知らせるしくみ)に、自分で書いた「render」のクロージャ(名前のない関数)を決めます。
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 を作ります。
use App\Http\Controllers\HomeController;
$url = action([HomeController::class, 'index']);
コントローラーのメソッドがルートパラメータを受け取るなら、2つ目の引数に、ルートパラメータの連想配列(名前と値の組の並び)を渡せます。
$url = action([UserController::class, 'profile'], ['id' => 1]);
Uri のオブジェクト#
Laravel の Uri クラスを使うと、URI(URL のなかま)をオブジェクト(クラスから作った実体)として作ったり、変えたりできます。このクラスは、League URI というパッケージ(ほかの人が作った部品)の機能を中で使っていて、Laravel のルーティングともうまくつながります。
static メソッド(クラス名から直接呼べるメソッド)で、Uri のオブジェクトを作れます。
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 のオブジェクトを作ったら、続けて書きかえられます。
$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}(言語の設定)のパラメータがあるとします。
Route::get('/{locale}/posts', function () {
// ...
})->name('post.index');
route を呼ぶたびに、locale を渡すのは面倒です。URL::defaults メソッドで、いまのリクエストの間、いつも使われる初期値を決められます。いまのリクエストを使えるように、ルートのミドルウェアから呼ぶとよいでしょう。
<?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 の、ミドルウェアの優先を決めるメソッドで書けます。
->withMiddleware(function (Middleware $middleware): void {
$middleware->prependToPriorityList(
before: \Illuminate\Routing\Middleware\SubstituteBindings::class,
prepend: \App\Http\Middleware\SetDefaultLocaleForUrls::class,
);
})
関連するページ#
公式ドキュメント(英語)
2026年10月5日時点の内容をもとに、日本語でまとめています。