URL Generation
Table of Contents
Introduction
Laravel は、 application の URL を生成するのを支援するためのいくつかの helpers を提供しています。これらの helpers は主に、テンプレートや API レスポンスで links を構築したり、 application の別の部分への redirect レスポンスを生成するときに役立ちます。
The Basics
URL の生成
url
helper は、あなたの application のための任意の URL を生成するために使用できます。生成された URL は自動的に現在の request が application によって処理されているス key ム(HTTP または HTTPS)とホストを使用します。
$post = App\Models\Post::find(1);
echo url("/posts/{$post->id}");
// http://example.com/posts/1
query
method を使用して、 query string パラメーター付きの URL を生成することができます。
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
path に既に存在する query string パラメータを提供すると、既存の value が上書きされます:
echo url()->query('/posts?sort=latest', ['sort' => 'oldest']);
// http://example.com/posts?sort=oldest
values の配列も query パラメータとして渡すことができます。これらの values は生成された 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
ヘルパーに対して path が提供されない場合、 Illuminate\Routing\UrlGenerator
インスタンスが返され、現在の URL に関する情報にアクセスできます。
// Get the current URL without the query string...
echo url()->current();
// Get the current URL including the query string...
echo url()->full();
// Get the full URL for the previous request...
echo url()->previous();
これらのメソッドはそれぞれ、URL
facadeを通じてアクセスすることも可能です:
use Illuminate\Support\Facades\URL;
echo URL::current();
URLs for Named Routes
route
helper は、名前付き routesの URL を生成するために使用できます。名前付き routes を使用すると、実際の URL が route 上で定義されているのに連動せずに URL を生成できます。したがって、route の URL が変更されても、route
関数への呼び出しに変更を加える必要はありません。例えば、あなたの application には以下のように定義された route が含まれていると想像してみてください:
Route::get('/post/{post}', function (Post $post) {
// ...
})->name('post.show');
この route への URL を生成するために、以下のように route
helper を使用することができます:
echo route('post.show', ['post' => 1]);
// http://example.com/post/1
もちろん、route
ヘルパーは、 routes の複数のパラメーターに対する URL を生成するためにも使用できます。
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
ルートの定義パラメータに対応しない追加の array elements は、URL の query string に追加されます。
echo route('post.show', ['post' => 1, 'search' => 'rocket']);
// http://example.com/post/1?search=rocket
Eloquent Models
あなたはしばしば、Eloquent modelsの route キー(通常は primary キー)を使用して URL を生成することがあります。そのため、 Eloquent models をパラメータ values として渡すことができます。route
ヘルパーは自動的にモデルの route キーを抽出します。
echo route('post.show', ['post' => $post]);
サイン付き URL
Laravel は、署名付きの routes への URL を簡単に作成することができます。これらの URL には hash 形式の署名が query string に追加されており、Laravel がそれが作成されてから URL が変更されていないことを確認することを可能にします。署名付きの URL は、公にアクセス可能でありながら URL の操作に対する保護層が必要な routes に特に有用です。
たとえば、署名付き URL を使用して、お客様に mail で送信される public の unsubscribelink を実装する場合があります。名前付き route への署名付き URL を作成するには、URL
facade の signedRoute
method を使用してください:
use Illuminate\Support\Facades\URL;
return URL::signedRoute('unsubscribe', ['user' => 1]);
signedRoute
method にabsolute
引数を提供することにより、署名付き URL hash から domain を除外することができます。
return URL::signedRoute('unsubscribe', ['user' => 1], absolute: false);
特定の時間が経過した後に有効期限が切れる一時的な署名付きの route URL を生成したい場合、temporarySignedRoute
method を使用することができます。 Laravel が一時的に署名された route URL を確認する際、署名付き URL にエンコードされた有効期限 timestamp がまだ経過していないことを確認します。
use Illuminate\Support\Facades\URL;
return URL::temporarySignedRoute(
'unsubscribe', now()->addMinutes(30), ['user' => 1]
);
Validating 署名済み Route リクエストの検証
着信の request が有効な signature を持っていることを確認するには、着信のIlluminate\Http\Request
インスタンスにhasValidSignature
method を呼び出すべきです:
use Illuminate\Http\Request;
Route::get('/unsubscribe/{user}', function (Request $request) {
if (! $request->hasValidSignature()) {
abort(401);
}
// ...
})->name('unsubscribe');
時々、クライアント側の pagination を実行するときなど、アプリケーションのフロントエンドが署名された URL に append data を追加できるようにする必要があるかもしれません。したがって、署名された URL の validating を行う際に無視するべき request query パラメータを hasValidSignatureWhileIgnoring
method を使用して指定することができます。覚えておいてください、パラメータを無視すると、誰でもそのパラメータを request 上で変更することができます:
if (! $request->hasValidSignatureWhileIgnoring(['page', 'order'])) {
abort(401);
}
受信した request インスタンスを使って validating 署名付き URL を検証する代わりに、signed
(Illuminate\Routing\Middleware\ValidateSignature
) middleware を route に割り当てることができます。受信した request に有効な signature がない場合、 middleware は自動的に403
HTTP response を返します。
Route::post('/unsubscribe/{user}', function (Request $request) {
// ...
})->name('unsubscribe')->middleware('signed');
もし署名付き URL が URL hash 内に domain を含んでいない場合、relative
引数を middleware に提供するべきです:
Route::post('/unsubscribe/{user}', function (Request $request) {
// ...
})->name('unsubscribe')->middleware('signed:relative');
Invalid と署名された Routes への対応
誰かが有効期限が切れた署名付きの URL を訪れると、彼らは一般的な error ページを403
の HTTP status コード で受け取ります。しかし、application のbootstrap/app.php
ファイルでInvalidSignatureException
例外のための custom レンダークロージャを定義することで、この振る舞いをカスタマイズすることができます。
use Illuminate\Routing\Exceptions\InvalidSignatureException;
->withExceptions(function (Exceptions $exceptions) {
$exceptions->render(function (InvalidSignatureException $e) {
return response()->view('error.link-expired', [], 403);
});
})
URLs for Controller Actions
action
関数は、指定された controller action のための URL を生成します:
use App\Http\Controllers\HomeController;
$url = action([HomeController::class, 'index']);
もし controller method が route パラメータを受け入れるのであれば、関数の第二引数として route パラメータの連想 array を渡すことができます:
$url = action([UserController::class, 'profile'], ['id' => 1]);
Default Values
一部の application では、特定の URL パラメータに対して request 全体の default values を指定したい場合があります。例えば、多くの routes で{locale}
パラメータを定義していると想像してみてください:
Route::get('/{locale}/posts', function () {
// ...
})->name('post.index');
route
helper を呼び出すたびに毎回 locale
を渡すのは面倒です。したがって、 URL::defaults
method を使用して、このパラメーターの default value を定義し、現在の request の間は常に適用できるようにすることができます。現在の request にアクセスできるように、この method をroute middlewareから呼び出すことを検討してみて下さい。
<?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
パラメータの defaultvalue が設定されると、route
helper を使用して URL を生成する際に、その value を渡す必要は必須ではなくなります。
URL Defaults と Middleware の優先度
URL default values を設定すると、Laravel の暗黙的な model バインディングの処理に干渉する可能性があります。そのため、SubstituteBindings
middleware よりも先に URL defaults を設定するmiddleware を優先させるべきです。これは、アプリケーションのbootstrap/app.php
ファイルの中のpriority
middleware method を使用して実現できます。
->withMiddleware(function (Middleware $middleware) {
$middleware->priority([
\Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
\Illuminate\Cookie\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class,
\Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class,
\Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\App\Http\Middleware\SetDefaultLocaleForUrls::class, // [tl! add]
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
]);
})