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时,不再需要传递其值。

查看笔记

扫码一下
查看教程更方便