はじめに

Laravelは、アプリケーションのURLを生成するためのいくつかのヘルパーを提供します。これらのヘルパーは、主にテンプレートやAPIレスポンスでリンクを構築する際、またはアプリケーションの別の部分へのリダイレクトレスポンスを生成する際に役立ちます。

基本

URLの生成

  1. ``````php
  2. $post = App\Models\Post::find(1);
  3. echo url("/posts/{$post->id}");
  4. // http://example.com/posts/1
  5. `

クエリ文字列パラメータを持つURLを生成するには、queryメソッドを使用できます:

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

パスに既に存在するクエリ文字列パラメータを提供すると、その既存の値が上書きされます:

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

値の配列もクエリパラメータとして渡すことができます。これらの値は、生成されたURLで適切にキー付けされ、エンコードされます:

  1. echo $url = url()->query('/posts', ['columns' => ['title', 'body']]);
  2. // http://example.com/posts?columns%5B0%5D=title&columns%5B1%5D=body
  3. echo urldecode($url);
  4. // http://example.com/posts?columns[0]=title&columns[1]=body

現在のURLへのアクセス

  1. ``````php
  2. // Get the current URL without the query string...
  3. echo url()->current();
  4. // Get the current URL including the query string...
  5. echo url()->full();
  6. // Get the full URL for the previous request...
  7. echo url()->previous();
  8. `

これらのメソッドのそれぞれは、URL ファサードを介してもアクセスできます:

  1. use Illuminate\Support\Facades\URL;
  2. echo URL::current();

名前付きルートのURL

  1. ``````php
  2. Route::get('/post/{post}', function (Post $post) {
  3. // ...
  4. })->name('post.show');
  5. `

このルートへのURLを生成するには、routeヘルパーを次のように使用できます:

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

もちろん、routeヘルパーを使用して、複数のパラメータを持つルートのURLを生成することもできます:

  1. Route::get('/post/{post}/comment/{comment}', function (Post $post, Comment $comment) {
  2. // ...
  3. })->name('comment.show');
  4. echo route('comment.show', ['post' => 1, 'comment' => 3]);
  5. // http://example.com/post/1/comment/3

ルートの定義パラメータに対応しない追加の配列要素は、URLのクエリ文字列に追加されます:

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

Eloquentモデル

あなたはしばしば、Eloquentモデルのルートキー(通常は主キー)を使用してURLを生成します。このため、Eloquentモデルをパラメータ値として渡すことができます。routeヘルパーは、自動的にモデルのルートキーを抽出します:

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

署名付きURL

Laravelは、名前付きルートへの「署名付き」URLを簡単に作成できるようにします。これらのURLには、クエリ文字列に「署名」ハッシュが追加されており、LaravelがURLが作成されて以来変更されていないことを確認できます。署名付きURLは、公開アクセス可能でありながらURL操作に対する保護層が必要なルートに特に便利です。

たとえば、署名付きURLを使用して、顧客にメールで送信される公開の「購読解除」リンクを実装することができます。名前付きルートへの署名付きURLを作成するには、signedRouteメソッドをURLファサードで使用します:

  1. use Illuminate\Support\Facades\URL;
  2. return URL::signedRoute('unsubscribe', ['user' => 1]);

署名付きURLハッシュからドメインを除外するには、absolute引数をsignedRouteメソッドに提供します:

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

指定された時間が経過した後に期限切れになる一時的な署名付きルートURLを生成したい場合は、temporarySignedRouteメソッドを使用できます。Laravelが一時的な署名付きルートURLを検証するとき、署名付きURLにエンコードされた有効期限のタイムスタンプが経過していないことを確認します:

  1. use Illuminate\Support\Facades\URL;
  2. return URL::temporarySignedRoute(
  3. 'unsubscribe', now()->addMinutes(30), ['user' => 1]
  4. );

署名付きルートリクエストの検証

受信リクエストに有効な署名があることを確認するには、受信したIlluminate\Http\RequestインスタンスでhasValidSignatureメソッドを呼び出す必要があります:

  1. use Illuminate\Http\Request;
  2. Route::get('/unsubscribe/{user}', function (Request $request) {
  3. if (! $request->hasValidSignature()) {
  4. abort(401);
  5. }
  6. // ...
  7. })->name('unsubscribe');

場合によっては、クライアント側のページネーションを行う際に、アプリケーションのフロントエンドが署名付きURLにデータを追加できるようにする必要があります。したがって、署名付きURLを検証する際に無視すべきリクエストクエリパラメータを指定できます。パラメータを無視することは、誰でもリクエストのそのパラメータを変更できることを意味します:

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

受信リクエストインスタンスを使用して署名付きURLを検証する代わりに、signedIlluminate\Routing\Middleware\ValidateSignatureミドルウェアをルートに割り当てることができます。受信リクエストに有効な署名がない場合、ミドルウェアは自動的に403 HTTPレスポンスを返します:

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

署名付きURLにドメインが含まれていない場合は、ミドルウェアにrelative引数を提供する必要があります:

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

無効な署名付きルートへの応答

誰かが期限切れの署名付きURLを訪れると、403 HTTPステータスコードの一般的なエラーページが表示されます。ただし、アプリケーションのbootstrap/app.phpファイルでInvalidSignatureException例外のカスタム「レンダリング」クロージャを定義することで、この動作をカスタマイズできます:

  1. use Illuminate\Routing\Exceptions\InvalidSignatureException;
  2. ->withExceptions(function (Exceptions $exceptions) {
  3. $exceptions->render(function (InvalidSignatureException $e) {
  4. return response()->view('errors.link-expired', status: 403);
  5. });
  6. })

コントローラーアクションのURL

  1. ``````php
  2. use App\Http\Controllers\HomeController;
  3. $url = action([HomeController::class, 'index']);
  4. `

コントローラーメソッドがルートパラメータを受け入れる場合、関数の第2引数としてルートパラメータの連想配列を渡すことができます:

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

デフォルト値

一部のアプリケーションでは、特定のURLパラメータに対してリクエスト全体のデフォルト値を指定したい場合があります。たとえば、多くのルートが{locale}パラメータを定義しているとします:

  1. Route::get('/{locale}/posts', function () {
  2. // ...
  3. })->name('post.index');
  1. ``````php
  2. <?php
  3. namespace App\Http\Middleware;
  4. use Closure;
  5. use Illuminate\Http\Request;
  6. use Illuminate\Support\Facades\URL;
  7. use Symfony\Component\HttpFoundation\Response;
  8. class SetDefaultLocaleForUrls
  9. {
  10. /**
  11. * Handle an incoming request.
  12. *
  13. * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
  14. */
  15. public function handle(Request $request, Closure $next): Response
  16. {
  17. URL::defaults(['locale' => $request->user()->locale]);
  18. return $next($request);
  19. }
  20. }
  21. `
  1. <a name="url-defaults-middleware-priority"></a>
  2. #### URLのデフォルトとミドルウェアの優先順位
  3. URLのデフォルト値を設定すると、Laravelの暗黙のモデルバインディングの処理に干渉する可能性があります。したがって、URLデフォルトを設定するミドルウェアの[優先順位を付ける](e83dea69e84000f7.md#sorting-middleware)必要があります。これにより、Laravel自身の`````SubstituteBindings`````ミドルウェアの前に実行されるようにできます。これを実現するには、アプリケーションの`````bootstrap/app.php`````ファイル内の`````priority`````ミドルウェアメソッドを使用します:
  4. ``````php
  5. ->withMiddleware(function (Middleware $middleware) {
  6. $middleware->priority([
  7. \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
  8. \Illuminate\Cookie\Middleware\EncryptCookies::class,
  9. \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
  10. \Illuminate\Session\Middleware\StartSession::class,
  11. \Illuminate\View\Middleware\ShareErrorsFromSession::class,
  12. \Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class,
  13. \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
  14. \Illuminate\Routing\Middleware\ThrottleRequests::class,
  15. \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class,
  16. \Illuminate\Session\Middleware\AuthenticateSession::class,
  17. \App\Http\Middleware\SetDefaultLocaleForUrls::class,
  18. \Illuminate\Routing\Middleware\SubstituteBindings::class,
  19. \Illuminate\Auth\Middleware\Authorize::class,
  20. ]);
  21. })
  22. `