Laravel 生成 URL
简介
Laravel提供了一些函数来帮助我们为应用程序生成URL。当在模板和API响应中构建链接,或生成指向应用程序另一部分的重定向响应时,这些方法非常有用。
基础知识
生成基本的URL
url帮助函数可用于为我们的应用程序生成任意URL。生成的URL将从当前的请求中自动获取协议(HTTP或HTTPS)和host:
$post = App\Post::find(1);
echo url("/posts/{$post->id}");
// http://example.com/posts/1
访问当前URL
如果没有给url函数传一个路径参数,则返回一个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();
给命名路由生成URL
route
函数可以通过命名路由的名称生成URL。使用路由的名称可以使得路由和生成的URL之间解耦合。因为,如果路由的URL更改,则无需对route函数调用进行任何更改。例如,假设我们应用程序包含如下定义的路由:
Route::get('/post/{post}', function () {
//
})->name('post.show');
要生成此路由的URL,可以使用下面的方法
echo route('post.show', ['post' => 1]);
// http://example.com/post/1
我们经常使用Eloquent模型的主键生成URL 。因此,可以将Eloquent模型作为参数值传递给route函数。route将自动提取模型的主键:
echo route('post.show', ['post' => $post]);
route帮助函数还可用于为具有多个参数的路由生成URL:
Route::get('/post/{post}/comment/{comment}', function () {
//
})->name('comment.show');
echo route('comment.show', ['post' => 1, 'comment' => 3]);
// http://example.com/post/1/comment/3
签名网址
Laravel使我们可以轻松地为命名路由创建“签名” URL。这些URL在query string后附加一个哈希值作为“签名”,这使得Laravel可以验证URL自创建以来是否被修改。签名的URL对于那些可公开访问的URL,但是需要防止被篡改特别有用。
例如,我们可以使用签名的URL来实现通过电子邮件发送给客户的公共“unsubscribe”链接。要创建命名路由的签名URL,可以使用URL Facade的signedRoute
方法:
use Illuminate\Support\Facades\URL;
return URL::signedRoute('unsubscribe', ['user' => 1]);
如果我们想生成一个有过期时间的临时签名路由URL,则可以使用以下temporarySignedRoute方法:
use Illuminate\Support\Facades\URL;
return URL::temporarySignedRoute(
'unsubscribe', now()->addMinutes(30), ['user' => 1]
);
验证签名的路由请求
要验证请求具有有效签名,应该在传入请求上调用Request 的hasValidSignature
方法:
use Illuminate\Http\Request;
Route::get('/unsubscribe/{user}', function (Request $request) {
if (! $request->hasValidSignature()) {
abort(401);
}
// ...
})->name('unsubscribe');
或者,我们可以将Illuminate\Routing\Middleware\ValidateSignature
中间件分配给路由。如果尚不存在,则应在HTTP Kernel 的routeMiddleware
数组中为该中间件分配一个键名:
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
];
一旦在内核中注册了中间件,就可以将其附加到路由上。如果传入的请求没有有效的签名,则中间件将自动返回403错误响应:
Route::post('/unsubscribe/{user}', function (Request $request) {
// ...
})->name('unsubscribe')->middleware('signed');
为控制的方法生成URL
action
函数为给定的控制器动作生成一个URL。我们不需要传递控制器的完整命名空间。而是传递在App\Http\Controllers
命名空间下的控制器类名称:
$url = action('HomeController@index');
我们还可以使用下面这种数组的形式调用action
use App\Http\Controllers\HomeController;
$url = action([HomeController::class, 'index']);
如果控制器的方法接受路由参数,则可以将它们作为第二个参数传递给action
:
$url = action('UserController@profile', ['id' => 1]);
默认值
对于某些应用程序,我们可能希望为某些URL参数指定请求范围的默认值。例如,假设我们的许多路由都定义了一个{locale}
参数:
Route::get('/{locale}/posts', function () {
//
})->name('post.index');
每次调用route
帮助函数时总是要传递locale
是很麻烦的。因此,可以使用URL::defaults
方法来定义此参数的默认值,该默认值将始终在当前请求期间应用。我们可能希望从路由中间件中调用此方法,以便可以访问当前请求:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\URL;
class SetDefaultLocaleForUrls
{
public function handle($request, Closure $next)
{
URL::defaults(['locale' => $request->user()->locale]);
return $next($request);
}
}
为locale参数设置默认值后,通过route
帮助函数生成URL时,不再需要传递其值。