Laravel 5.5 LTS からルート専用ルーティング Route::redirect
が使用可能になりました。これにより、リダイレクトのためだけにわざわざコントローラーにメソッドを生やしたりする必要がなくなり、URL変更時のリダイレクトなどが容易になりました。
もくじ
Syntax
1 |
Route::redirect($uri, $destination, $status = 301) |
使い方
1 2 |
Route::redirect('/from', '/to'); // https://example.com/to へ 301リダイレクト Route::redirect('/yahoo', 'https://yahoo.co.jp/', 302); // https://yahoo.com/ へ 302リダイレクト |
使用上の注意
$destination
はURIでのみ指定でき、ルート名での指定は出来ない。
Route::redirect('hoge', route('fuga'))
のようにでも出来ればいいところだが、この時点ではまだ登録が未完了なため Route [fuga] not defined. となってしまう。(Router
はMacroableなので結局それが必要ならマクロはやしたほうがいいのか……)
内部実装
vendor/laravel/framework/src/Illuminate/Routing/Router.php:215
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/** * Create a redirect from one URI to another. * * @param string $uri * @param string $destination * @param int $status * @return \Illuminate\Routing\Route */ public function redirect($uri, $destination, $status = 301) { return $this->any($uri, '\Illuminate\Routing\RedirectController') ->defaults('destination', $destination) ->defaults('status', $status); } |
vendor/laravel/framework/src/Illuminate/Routing/RedirectController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php namespace Illuminate\Routing; use Illuminate\Http\RedirectResponse; class RedirectController extends Controller { /** * Invoke the controller method. * * @param string $destination * @param int $status * @return \Illuminate\Http\RedirectResponse */ public function __invoke($destination, $status = 301) { return new RedirectResponse($destination, $status); } } |
といった専用のコントローラーをfw側に用意し、それを呼び出すルートとして登録している。
バックポート
上記のような単純な構成になっているため、同内容をマクロとして登録してやることで以前のバージョンのLaravelでも同様の記法が使える。(また、揃えておけば5.5アップデート時にそのままFWのRoute::redirect
を使えるので便利)
登録例:
適当な箇所 (RouteServiceProvider::boot
など)でmacroを登録
1 2 3 4 5 6 7 8 9 10 11 12 |
... public function boot() { Route::macro('redirect', function($uri, $destination, $status = 301) { return $this->any($uri, '\App\Http\Controllers\RedirectController') ->defaults('destination', $destination) ->defaults('status', $status); }); parent::boot(); } ... |
対応するControllerを作成 (ここではRedirectController)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php namespace App\Http\Controllers; use Illuminate\Http\RedirectResponse; class RedirectController extends Controller { public function __invoke($destination, $status = 301) { return new RedirectResponse($destination, $status); } } |
(Route::group内でベース名前空間が変わったりしても問題ないようフルの名前空間使用&__invoke
を使用している)
応用
上記バックポートを少し改造することでルート名でリダイレクトを設定することも可能。(といってもURLに含まれるパラメタをリダイレクトに含みたいときはコントローラー生やしたほうが良さそう。)
1 2 3 4 5 6 |
Route::macro('redirectRoute', function ($uri, $route, $params = [], $status = 301) { return $this->any($uri, '\App\Http\Controllers\RedirectToRouteController') ->defaults('route', $route) ->defaults('params', $params) ->defaults('status', $status); }); |
1 2 3 4 5 6 7 8 9 10 11 |
<?php namespace App\Http\Controllers; class RedirectToRouteController extends Controller { public function __invoke($route, $params = [], $status = 301) { return redirect()->route($route, $params, $status); } } |
これにより Route::redirectRoute('/from', 'welcome', [], 302);
のようなSyntaxで名前付きルートへのリダイレクトが設定できる。
Official doc: Routing#Redirect Routes