跳至内容

路由

基本路由

最基本的 Laravel 路由接受 URI 和闭包,提供了一种非常简单且富有表现力的定义路由和行为的方法,无需复杂的路由配置文件。

use Illuminate\Support\Facades\Route;
 
Route::get('/greeting', function () {
return 'Hello World';
});

默认路由文件

所有 Laravel 路由都定义在您的路由文件中,这些文件位于 routes 目录中。Laravel 使用应用程序的 bootstrap/app.php 文件中指定的配置自动加载这些文件。routes/web.php 文件定义了 Web 界面使用的路由。这些路由被分配了 web 中间件组,该组提供诸如会话状态和 CSRF 保护等功能。

对于大多数应用程序,您将首先在 routes/web.php 文件中定义路由。routes/web.php 中定义的路由可以通过在浏览器中输入定义的路由的 URL 来访问。例如,您可以通过在浏览器中导航到 http://example.com/user 来访问以下路由。

use App\Http\Controllers\UserController;
 
Route::get('/user', [UserController::class, 'index']);

API 路由

如果您的应用程序也将提供一个无状态 API,则可以使用 install:api Artisan 命令启用 API 路由。

php artisan install:api

install:api 命令安装了 Laravel Sanctum,它提供了一个强大且简单的 API 令牌身份验证守卫,可用于对第三方 API 消费者、SPA 或移动应用程序进行身份验证。此外,install:api 命令创建了 routes/api.php 文件。

Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:sanctum');

routes/api.php 中的路由是无状态的,并被分配到 api 中间件组。此外,/api URI 前缀会自动应用于这些路由,因此您无需手动将其应用于文件中的每个路由。您可以通过修改应用程序的 bootstrap/app.php 文件来更改前缀。

->withRouting(
api: __DIR__.'/../routes/api.php',
apiPrefix: 'api/admin',
// ...
)

可用的路由器方法

路由器允许您注册响应任何 HTTP 方法的路由。

Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);

有时您可能需要注册一个响应多个 HTTP 方法的路由。您可以使用 match 方法来实现。或者,您甚至可以使用 any 方法注册一个响应所有 HTTP 方法的路由。

Route::match(['get', 'post'], '/', function () {
// ...
});
 
Route::any('/', function () {
// ...
});
lightbulb

在定义多个共享相同 URI 的路由时,使用 getpostputpatchdeleteoptions 方法的路由应在使用 anymatchredirect 方法的路由之前定义。这确保了传入请求与正确的路由匹配。

依赖注入

您可以在路由回调签名中键入提示路由所需的任何依赖项。声明的依赖项将由 Laravel 服务容器 自动解析并注入回调。例如,您可以键入提示 Illuminate\Http\Request 类,以使当前 HTTP 请求自动注入到您的路由回调中。

use Illuminate\Http\Request;
 
Route::get('/users', function (Request $request) {
// ...
});

CSRF 保护

请记住,任何指向 web 路由文件中定义的 POSTPUTPATCHDELETE 路由的 HTML 表单都应包含一个 CSRF 令牌字段。否则,请求将被拒绝。您可以在 CSRF 文档 中阅读更多关于 CSRF 保护的信息。

<form method="POST" action="/profile">
@csrf
...
</form>

重定向路由

如果要定义一个重定向到另一个 URI 的路由,可以使用 Route::redirect 方法。此方法提供了一个便捷的快捷方式,因此您无需为执行简单的重定向定义完整的路由或控制器。

Route::redirect('/here', '/there');

默认情况下,Route::redirect 返回 302 状态代码。您可以使用可选的第三个参数自定义状态代码。

Route::redirect('/here', '/there', 301);

或者,您可以使用 Route::permanentRedirect 方法返回 301 状态代码。

Route::permanentRedirect('/here', '/there');
exclamation

在重定向路由中使用路由参数时,以下参数由 Laravel 保留,不能使用:destinationstatus

视图路由

如果您的路由只需要返回一个 视图,则可以使用 Route::view 方法。与 redirect 方法类似,此方法提供了一个简单的快捷方式,因此您无需定义完整的路由或控制器。view 方法接受 URI 作为其第一个参数,并接受视图名称作为其第二个参数。此外,您可以提供一个数据数组作为可选的第三个参数传递给视图。

Route::view('/welcome', 'welcome');
 
Route::view('/welcome', 'welcome', ['name' => 'Taylor']);
exclamation

在视图路由中使用路由参数时,以下参数由 Laravel 保留,不能使用:viewdatastatusheaders

列出您的路由

route:list Artisan 命令可以轻松提供应用程序中所有定义的路由的概述。

php artisan route:list

默认情况下,分配给每个路由的路由中间件不会显示在 route:list 输出中;但是,您可以指示 Laravel 显示路由中间件和中间件组名称,方法是在命令中添加 -v 选项。

php artisan route:list -v
 
# Expand middleware groups...
php artisan route:list -vv

您还可以指示 Laravel 仅显示以给定 URI 开头的路由。

php artisan route:list --path=api

此外,您可以指示 Laravel 隐藏第三方包定义的任何路由,方法是在执行 route:list 命令时提供 --except-vendor 选项。

php artisan route:list --except-vendor

同样,您还可以指示 Laravel 仅显示第三方包定义的路由,方法是在执行 route:list 命令时提供 --only-vendor 选项。

php artisan route:list --only-vendor

路由自定义

默认情况下,应用程序的路由由 bootstrap/app.php 文件配置和加载。

<?php
 
use Illuminate\Foundation\Application;
 
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)->create();

但是,有时您可能希望定义一个全新的文件来包含应用程序路由的子集。要实现此目的,您可以为 withRouting 方法提供一个 then 闭包。在此闭包中,您可以注册应用程序所需的任何其他路由。

use Illuminate\Support\Facades\Route;
 
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
then: function () {
Route::middleware('api')
->prefix('webhooks')
->name('webhooks.')
->group(base_path('routes/webhooks.php'));
},
)

或者,您甚至可以通过为 withRouting 方法提供一个 using 闭包来完全控制路由注册。传递此参数时,框架将不会注册任何 HTTP 路由,您负责手动注册所有路由。

use Illuminate\Support\Facades\Route;
 
->withRouting(
commands: __DIR__.'/../routes/console.php',
using: function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));
 
Route::middleware('web')
->group(base_path('routes/web.php'));
},
)

路由参数

必需参数

有时您需要捕获 URI 中的片段。例如,您可能需要从 URL 中捕获用户的 ID。您可以通过定义路由参数来实现。

Route::get('/user/{id}', function (string $id) {
return 'User '.$id;
});

您可以根据路由需要定义任意数量的路由参数。

Route::get('/posts/{post}/comments/{comment}', function (string $postId, string $commentId) {
// ...
});

路由参数始终用{}括号括起来,并且应该由字母字符组成。下划线 (_) 也可在路由参数名称中使用。路由参数根据其顺序注入路由回调/控制器 - 路由回调/控制器参数的名称无关紧要。

参数和依赖注入

如果您的路由具有希望 Laravel 服务容器自动注入到路由回调中的依赖项,则应在依赖项之后列出路由参数

use Illuminate\Http\Request;
 
Route::get('/user/{id}', function (Request $request, string $id) {
return 'User '.$id;
});

可选参数

有时您可能需要指定一个 URI 中可能并不总是存在的路由参数。您可以通过在参数名称后放置?标记来做到这一点。确保为路由的相应变量提供默认值

Route::get('/user/{name?}', function (?string $name = null) {
return $name;
});
 
Route::get('/user/{name?}', function (?string $name = 'John') {
return $name;
});

正则表达式约束

您可以使用路由实例上的where方法来约束路由参数的格式。where方法接受参数的名称和一个正则表达式,用于定义如何约束参数

Route::get('/user/{name}', function (string $name) {
// ...
})->where('name', '[A-Za-z]+');
 
Route::get('/user/{id}', function (string $id) {
// ...
})->where('id', '[0-9]+');
 
Route::get('/user/{id}/{name}', function (string $id, string $name) {
// ...
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);

为了方便起见,一些常用的正则表达式模式具有辅助方法,允许您快速将模式约束添加到路由中

Route::get('/user/{id}/{name}', function (string $id, string $name) {
// ...
})->whereNumber('id')->whereAlpha('name');
 
Route::get('/user/{name}', function (string $name) {
// ...
})->whereAlphaNumeric('name');
 
Route::get('/user/{id}', function (string $id) {
// ...
})->whereUuid('id');
 
Route::get('/user/{id}', function (string $id) {
// ...
})->whereUlid('id');
 
Route::get('/category/{category}', function (string $category) {
// ...
})->whereIn('category', ['movie', 'song', 'painting']);
 
Route::get('/category/{category}', function (string $category) {
// ...
})->whereIn('category', CategoryEnum::cases());

如果传入的请求与路由模式约束不匹配,则将返回 404 HTTP 响应。

全局约束

如果您希望路由参数始终受给定正则表达式的约束,则可以使用pattern方法。您应该在应用程序的App\Providers\AppServiceProvider类的boot方法中定义这些模式

use Illuminate\Support\Facades\Route;
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Route::pattern('id', '[0-9]+');
}

定义模式后,它将自动应用于使用该参数名称的所有路由

Route::get('/user/{id}', function (string $id) {
// Only executed if {id} is numeric...
});

编码正斜杠

Laravel 路由组件允许除/之外的所有字符出现在路由参数值中。您必须使用where条件正则表达式显式允许/作为占位符的一部分

Route::get('/search/{search}', function (string $search) {
return $search;
})->where('search', '.*');
exclamation

编码正斜杠仅在最后一个路由段中受支持。

命名路由

命名路由允许方便地为特定路由生成 URL 或重定向。您可以通过将name方法链接到路由定义来为路由指定名称

Route::get('/user/profile', function () {
// ...
})->name('profile');

您也可以为控制器操作指定路由名称

Route::get(
'/user/profile',
[UserProfileController::class, 'show']
)->name('profile');
exclamation

路由名称应始终唯一。

生成到命名路由的 URL

为给定路由分配名称后,您可以在使用 Laravel 的routeredirect辅助函数生成 URL 或重定向时使用路由的名称

// Generating URLs...
$url = route('profile');
 
// Generating Redirects...
return redirect()->route('profile');
 
return to_route('profile');

如果命名路由定义了参数,则可以将参数作为第二个参数传递给route函数。给定的参数将自动插入到生成的 URL 中的正确位置

Route::get('/user/{id}/profile', function (string $id) {
// ...
})->name('profile');
 
$url = route('profile', ['id' => 1]);

如果在数组中传递其他参数,则这些键/值对将自动添加到生成的 URL 的查询字符串中

Route::get('/user/{id}/profile', function (string $id) {
// ...
})->name('profile');
 
$url = route('profile', ['id' => 1, 'photos' => 'yes']);
 
// /user/1/profile?photos=yes
lightbulb

有时,您可能希望为 URL 参数指定请求范围的默认值,例如当前语言环境。为此,您可以使用URL::defaults方法

检查当前路由

如果您想确定当前请求是否已路由到给定的命名路由,则可以使用路由实例上的named方法。例如,您可以从路由中间件检查当前路由名称

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
 
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if ($request->route()->named('profile')) {
// ...
}
 
return $next($request);
}

路由组

路由组允许您在大量路由中共享路由属性(例如中间件),而无需在每个单独的路由上定义这些属性。

嵌套组尝试智能地将其属性与父组“合并”。中间件和where条件被合并,而名称和前缀则被追加。在适当的地方会自动添加 URI 前缀中的命名空间分隔符和斜杠。

中间件

要将中间件分配给组中的所有路由,可以在定义组之前使用middleware方法。中间件按其在数组中列出的顺序执行

Route::middleware(['first', 'second'])->group(function () {
Route::get('/', function () {
// Uses first & second middleware...
});
 
Route::get('/user/profile', function () {
// Uses first & second middleware...
});
});

控制器

如果一组路由都使用相同的控制器,则可以使用controller方法为组中的所有路由定义公共控制器。然后,在定义路由时,您只需要提供它们调用的控制器方法

use App\Http\Controllers\OrderController;
 
Route::controller(OrderController::class)->group(function () {
Route::get('/orders/{id}', 'show');
Route::post('/orders', 'store');
});

子域名路由

路由组也可用于处理子域路由。子域可以像路由 URI 一样分配路由参数,允许您捕获子域的一部分以在您的路由或控制器中使用。子域可以通过在定义组之前调用domain方法来指定

Route::domain('{account}.example.com')->group(function () {
Route::get('/user/{id}', function (string $account, string $id) {
// ...
});
});
exclamation

为了确保您的子域路由可访问,您应该在注册根域路由之前注册子域路由。这将防止根域路由覆盖具有相同 URI 路径的子域路由。

路由前缀

prefix方法可用于为组中的每个路由添加给定的 URI 前缀。例如,您可能希望为组中所有路由的 URI 添加admin前缀

Route::prefix('admin')->group(function () {
Route::get('/users', function () {
// Matches The "/admin/users" URL
});
});

路由名称前缀

name方法可用于为组中的每个路由名称添加给定的字符串前缀。例如,您可能希望为组中所有路由的名称添加admin前缀。给定的字符串将完全按照指定的方式添加到路由名称前,因此我们将确保在前缀中提供尾随.字符

Route::name('admin.')->group(function () {
Route::get('/users', function () {
// Route assigned name "admin.users"...
})->name('users');
});

路由模型绑定

在将模型 ID 注入到路由或控制器操作时,您通常会查询数据库以检索与该 ID 对应的模型。Laravel 路由模型绑定提供了一种方便的方法,可以将模型实例自动注入到您的路由中。例如,您可以注入与给定 ID 匹配的整个User模型实例,而不是注入用户的 ID。

隐式绑定

Laravel 会自动解析在路由或控制器操作中定义的 Eloquent 模型,其类型提示变量名称与路由段名称匹配。例如

use App\Models\User;
 
Route::get('/users/{user}', function (User $user) {
return $user->email;
});

由于$user变量被类型提示为App\Models\User Eloquent 模型,并且变量名称与{user}URI 段匹配,因此 Laravel 将自动注入与来自请求 URI 的相应值匹配的 ID 的模型实例。如果在数据库中找不到匹配的模型实例,则会自动生成 404 HTTP 响应。

当然,在使用控制器方法时也可以进行隐式绑定。再次注意,{user}URI 段匹配控制器中的$user变量,该变量包含App\Models\User类型提示

use App\Http\Controllers\UserController;
use App\Models\User;
 
// Route definition...
Route::get('/users/{user}', [UserController::class, 'show']);
 
// Controller method definition...
public function show(User $user)
{
return view('user.profile', ['user' => $user]);
}

软删除模型

通常,隐式模型绑定不会检索已软删除的模型。但是,您可以通过将withTrashed方法链接到路由的定义来指示隐式绑定检索这些模型

use App\Models\User;
 
Route::get('/users/{user}', function (User $user) {
return $user->email;
})->withTrashed();

自定义键

有时您可能希望使用除id之外的其他列来解析 Eloquent 模型。为此,您可以在路由参数定义中指定列

use App\Models\Post;
 
Route::get('/posts/{post:slug}', function (Post $post) {
return $post;
});

如果您希望模型绑定在检索给定模型类时始终使用除id之外的数据库列,则可以在 Eloquent 模型上覆盖getRouteKeyName方法

/**
* Get the route key for the model.
*/
public function getRouteKeyName(): string
{
return 'slug';
}

自定义键和作用域

当在一个路由定义中隐式绑定多个 Eloquent 模型时,您可能希望对第二个 Eloquent 模型进行作用域,使其必须是先前 Eloquent 模型的子项。例如,考虑此路由定义,它按特定用户的 slug 检索博客文章

use App\Models\Post;
use App\Models\User;
 
Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
return $post;
});

当使用自定义键控隐式绑定作为嵌套路由参数时,Laravel 会自动对查询进行作用域以使用约定来猜测父级上的关系名称检索嵌套模型。在这种情况下,将假设User模型具有名为posts(路由参数名称的复数形式)的关系,该关系可用于检索Post模型。

如果需要,您可以在定义路由时调用scopeBindings方法来指示 Laravel 对“子项”绑定进行作用域,即使未提供自定义键也是如此

use App\Models\Post;
use App\Models\User;
 
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
return $post;
})->scopeBindings();

或者,您可以指示整个路由定义组使用作用域绑定

Route::scopeBindings()->group(function () {
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
return $post;
});
});

同样,您可以通过调用withoutScopedBindings方法显式指示 Laravel 不要对绑定进行作用域

Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
return $post;
})->withoutScopedBindings();

自定义缺少模型的行为

通常,如果找不到隐式绑定的模型,则会生成 404 HTTP 响应。但是,您可以通过在定义路由时调用missing方法来自定义此行为。missing方法接受一个闭包,如果找不到隐式绑定的模型,则将调用该闭包

use App\Http\Controllers\LocationsController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
 
Route::get('/locations/{location:slug}', [LocationsController::class, 'show'])
->name('locations.view')
->missing(function (Request $request) {
return Redirect::route('locations.index');
});

隐式枚举绑定

PHP 8.1 引入了对枚举的支持。为了补充此功能,Laravel 允许您在路由定义上类型提示支持的枚举,并且 Laravel 仅在该路由段对应于有效的枚举值时才会调用该路由。否则,将自动返回 404 HTTP 响应。例如,给定以下枚举

<?php
 
namespace App\Enums;
 
enum Category: string
{
case Fruits = 'fruits';
case People = 'people';
}

您可以定义一个路由,该路由仅在{category}路由段为fruitspeople时才会被调用。否则,Laravel 将返回 404 HTTP 响应

use App\Enums\Category;
use Illuminate\Support\Facades\Route;
 
Route::get('/categories/{category}', function (Category $category) {
return $category->value;
});

显式绑定

您无需使用 Laravel 的隐式、基于约定的模型解析即可使用模型绑定。您还可以显式定义路由参数如何对应于模型。要注册显式绑定,请使用路由器的model方法为给定参数指定类。您应该在AppServiceProvider类的boot方法的开头定义显式模型绑定

use App\Models\User;
use Illuminate\Support\Facades\Route;
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Route::model('user', User::class);
}

接下来,定义一个包含{user}参数的路由

use App\Models\User;
 
Route::get('/users/{user}', function (User $user) {
// ...
});

由于我们已将所有{user}参数绑定到App\Models\User模型,因此将向路由注入该类的实例。因此,例如,对users/1的请求将注入数据库中 ID 为1User实例。

如果在数据库中找不到匹配的模型实例,则会自动生成 404 HTTP 响应。

自定义解析逻辑

如果您希望定义自己的模型绑定解析逻辑,则可以使用Route::bind方法。传递给bind方法的闭包将接收 URI 段的值,并应返回应注入路由的类的实例。同样,此自定义应发生在应用程序的AppServiceProvider类的boot方法中

use App\Models\User;
use Illuminate\Support\Facades\Route;
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Route::bind('user', function (string $value) {
return User::where('name', $value)->firstOrFail();
});
}

或者,您可以在 Eloquent 模型上覆盖resolveRouteBinding方法。此方法将接收 URI 段的值,并应返回应注入路由的类的实例

/**
* Retrieve the model for a bound value.
*
* @param mixed $value
* @param string|null $field
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function resolveRouteBinding($value, $field = null)
{
return $this->where('name', $value)->firstOrFail();
}

如果路由正在使用隐式模型绑定作用域,则将使用resolveChildRouteBinding方法解析父模型的子项绑定

/**
* Retrieve the child model for a bound value.
*
* @param string $childType
* @param mixed $value
* @param string|null $field
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function resolveChildRouteBinding($childType, $value, $field)
{
return parent::resolveChildRouteBinding($childType, $value, $field);
}

回退路由

使用Route::fallback方法,您可以定义一个路由,当没有其他路由与传入请求匹配时将执行该路由。通常,未处理的请求将通过应用程序的异常处理程序自动呈现“404”页面。但是,由于您通常会在routes/web.php文件中定义fallback路由,因此web中间件组中的所有中间件都将应用于该路由。您可以根据需要向此路由添加其他中间件

Route::fallback(function () {
// ...
});
exclamation

回退路由应始终是应用程序注册的最后一个路由。

速率限制

定义速率限制器

Laravel 包含强大且可自定义的限流服务,您可以利用这些服务来限制给定路由或路由组的流量。要开始使用,您应该定义满足应用程序需求的限流器配置。

限流器可以在应用程序的 App\Providers\AppServiceProvider 类中的 boot 方法中定义。

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
 
/**
* Bootstrap any application services.
*/
protected function boot(): void
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
}

限流器是使用 RateLimiter 门面的 for 方法定义的。for 方法接受一个限流器名称和一个闭包,该闭包返回应应用于分配给限流器的路由的限制配置。限制配置是 Illuminate\Cache\RateLimiting\Limit 类的实例。此类包含有用的“构建器”方法,以便您可以快速定义您的限制。限流器名称可以是您想要的任何字符串。

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
 
/**
* Bootstrap any application services.
*/
protected function boot(): void
{
RateLimiter::for('global', function (Request $request) {
return Limit::perMinute(1000);
});
}

如果传入请求超过指定的速率限制,Laravel 将自动返回带有 429 HTTP 状态代码的响应。如果您想定义自己的响应,该响应应由速率限制返回,您可以使用 response 方法。

RateLimiter::for('global', function (Request $request) {
return Limit::perMinute(1000)->response(function (Request $request, array $headers) {
return response('Custom response...', 429, $headers);
});
});

由于限流器回调接收传入的 HTTP 请求实例,因此您可以根据传入请求或已认证用户动态构建适当的速率限制。

RateLimiter::for('uploads', function (Request $request) {
return $request->user()->vipCustomer()
? Limit::none()
: Limit::perMinute(100);
});

细分速率限制

有时您可能希望按某些任意值细分速率限制。例如,您可能希望允许用户每分钟访问给定路由 100 次,每个 IP 地址一次。为此,您可以在构建速率限制时使用 by 方法。

RateLimiter::for('uploads', function (Request $request) {
return $request->user()->vipCustomer()
? Limit::none()
: Limit::perMinute(100)->by($request->ip());
});

为了使用另一个示例说明此功能,我们可以将对路由的访问限制为每分钟对已认证用户 ID 限制 100 次,或对访客每分钟限制 10 次 IP 地址。

RateLimiter::for('uploads', function (Request $request) {
return $request->user()
? Limit::perMinute(100)->by($request->user()->id)
: Limit::perMinute(10)->by($request->ip());
});

多个速率限制

如果需要,您可以为给定的限流器配置返回一个速率限制数组。每个速率限制都将根据它们在数组中的位置顺序针对路由进行评估。

RateLimiter::for('login', function (Request $request) {
return [
Limit::perMinute(500),
Limit::perMinute(3)->by($request->input('email')),
];
});

如果您正在分配多个由相同 by 值细分的速率限制,则应确保每个 by 值都是唯一的。实现此目的最简单的方法是在提供给 by 方法的值前面添加前缀。

RateLimiter::for('uploads', function (Request $request) {
return [
Limit::perMinute(10)->by('minute:'.$request->user()->id),
Limit::perDay(1000)->by('day:'.$request->user()->id),
];
});

将速率限制器附加到路由

限流器可以使用 throttle 中间件 附加到路由或路由组。throttle 中间件接受您希望分配给路由的限流器名称。

Route::middleware(['throttle:uploads'])->group(function () {
Route::post('/audio', function () {
// ...
});
 
Route::post('/video', function () {
// ...
});
});

使用 Redis 进行限流

默认情况下,throttle 中间件映射到 Illuminate\Routing\Middleware\ThrottleRequests 类。但是,如果您使用 Redis 作为应用程序的缓存驱动程序,则可能希望指示 Laravel 使用 Redis 来管理限流。为此,您应该在应用程序的 bootstrap/app.php 文件中使用 throttleWithRedis 方法。此方法将 throttle 中间件映射到 Illuminate\Routing\Middleware\ThrottleRequestsWithRedis 中间件类。

->withMiddleware(function (Middleware $middleware) {
$middleware->throttleWithRedis();
// ...
})

表单方法欺骗

HTML 表单不支持 PUTPATCHDELETE 操作。因此,当定义从 HTML 表单调用的 PUTPATCHDELETE 路由时,您需要在表单中添加一个隐藏的 _method 字段。使用 _method 字段发送的值将用作 HTTP 请求方法。

<form action="/example" method="POST">
<input type="hidden" name="_method" value="PUT">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>

为了方便起见,您可以使用 @method Blade 指令 生成 _method 输入字段。

<form action="/example" method="POST">
@method('PUT')
@csrf
</form>

访问当前路由

您可以使用 Route 门面上的 currentcurrentRouteNamecurrentRouteAction 方法来访问有关处理传入请求的路由的信息。

use Illuminate\Support\Facades\Route;
 
$route = Route::current(); // Illuminate\Routing\Route
$name = Route::currentRouteName(); // string
$action = Route::currentRouteAction(); // string

您可以参考 Route 门面底层类Route 实例 的 API 文档,以查看路由器和路由类上可用的所有方法。

跨源资源共享 (CORS)

Laravel 可以使用您配置的值自动响应 CORS OPTIONS HTTP 请求。OPTIONS 请求将由自动包含在应用程序全局中间件堆栈中的 HandleCors 中间件 自动处理。

有时,您可能需要自定义应用程序的 CORS 配置值。您可以使用 config:publish Artisan 命令发布 cors 配置文件来做到这一点。

php artisan config:publish cors

此命令将在应用程序的 config 目录中放置一个 cors.php 配置文件。

lightbulb

有关 CORS 和 CORS 标头的更多信息,请查阅 MDN 上关于 CORS 的网络文档

路由缓存

将应用程序部署到生产环境时,您应该利用 Laravel 的路由缓存。使用路由缓存将大大减少注册应用程序所有路由所需的时间。要生成路由缓存,请执行 route:cache Artisan 命令。

php artisan route:cache

运行此命令后,您的缓存路由文件将在每次请求时加载。请记住,如果您添加了任何新路由,则需要生成新的路由缓存。因此,您应该只在项目的部署过程中运行 route:cache 命令。

您可以使用 route:clear 命令清除路由缓存。

php artisan route:clear