掌握Laravel路由

掌握Laravel路由

当涉及到后端时,开发人员最终会遇到路由。路由可以被认为是后台的骨干,因为服务器收到的每个请求都会通过路由列表重定向到一个控制器,将请求映射到控制器或动作。

Laravel为我们隐藏了许多实现细节,并配有大量的语法糖,以帮助新的和有经验的开发人员开发他们的Web应用程序。

  1. 后台路由和跨站脚本在Laravel中的应用
  2. Laravel基本路由
  3. 路由参数
  4. 命名的路由
  5. 路由组
  6. 路由缓存

后台路由和跨站脚本在Laravel中的应用

在一个服务器上,存在着公共和私人路由。由于跨网站脚本(XSS)的可能性,公共路由可能是一个令人担忧的问题,这种类型的注入攻击可能使你和你的用户容易受到恶意行为者的攻击

问题是,用户可以从一个不需要会话令牌的路由重定向到一个需要会话令牌的路由–而且他们仍然可以在没有令牌的情况下访问。

解决这个问题的最简单方法是执行一个新的HTTP头,在路由中加入 “referrer”,以缓解这种情况:

'main' => [
'path' => '/main',
'referrer' => 'required,refresh-empty',
'target' => Controller\DashboardController::class . '::mainAction'
]

Laravel基本路由

在Laravel中, 路由允许用户将适当的请求路由到所需的控制器。最基本的Laravel路由接受一个统一的资产标识符(你的路由路径)和一个闭包,可以是一个函数或一个类。

在Laravel中, 路由是在web.phpapi.php文件中创建的. Laravel默认有两个路由: 一个用于WEB, 一个用于API.

这些路由位于routes/文件夹中, 但它们是在Providers/RouteServiceProvider.php中加载的。

Laravel的路由服务提供者的默认状态

Laravel的路由服务提供者的默认状态

与其这样,我们可以直接在RouteServiceProvider.php中加载路由,完全跳过routes/文件夹。

直接在供应商中加载Laravel路由

直接在供应商中加载Laravel路由

重定向

当我们定义一个路由时,我们通常会想重定向访问它的用户,而这样做的原因有很多。这可能是因为它是一个废弃的路由,我们已经改变了后台或服务器,也可能是因为我们想安装双因素认证(2FA),等等。

Laravel有一个简单的方法来做到这一点。由于该框架的简单性, 我们可以使用Route facade上的重定向方法, 它接受入口路线和要重定向的路线.

另外,我们可以把重定向的状态代码作为第三个参数。 permanentRedirect 方法的作用与 redirect 方法相同,只是它总是返回一个301状态代码

// Simple redirect
Route::redirect("/class", "/myClass");
// Redirect with custom status
Route::redirect("/home", "/office", 305);
// Route redirect with 301 status code
Route::permanentRedirect("/home", "office");

在重定向路线中,我们禁止使用 “destination “和 “status “关键字作为参数,因为它们是Laravel保留的。

// Illegal to use
Route::redirect("/home", "/office/{status}");

视图

视图是 .blade.php 文件,我们用它来渲染我们Laravel应用程序的前端。它使用了blade模板引擎, 它是只使用Laravel构建全栈应用的默认方式。

如果我们想让我们的路由返回一个视图, 我们可以简单地使用路由界面上的视图方法。它接受一个路由参数,一个视图名称,和一个可选的值数组来传递给视图。

// When the user accesses my-domain.com/homepage
// the homepage.blade.php file will be rendered
Route::view("/homepage", "homepage");

让我们假设我们的视图想说“Hello, {name}”,通过传递一个带有该参数的可选数组。我们可以用下面的代码来实现这个目的(如果视图中缺少的参数是必需的,那么请求就会失败并抛出一个错误):

Route::view('/homepage', 'homepage', ['name' => "Wbolt"]);

路由列表

随着你的应用程序规模的增长,需要路由的请求的数量也会增加。而大量的信息会带来巨大的混乱。

这就是 artisan route:list command 可以帮助我们的地方。它提供了一个在应用程序中定义的所有路由、它们的中间件和控制器的概览。

php artisan route:list

它将显示一个不含中间件的所有路由的列表。为此,我们必须使用 -v 标志。

php artisan route:list -v

在你可能使用域驱动设计的情况下,你的路由在其路径中具有特定的名称,你可以像这样利用这个命令的过滤功能:

php artisan route:list –path=api/account

这将只显示以api/account开头的路由。

另一方面, 我们可以通过使用 –except-vendor 或 –only-vendor 选项来指示Laravel排除或包括第三方定义的路由.

路由参数

有时你可能需要用路由来捕获URI的片段,如用户ID或令牌。我们可以通过定义一个路由参数来做到这一点, 这个参数总是被包裹在大括号里 ({}) , 而且应该只由字母组成.

如果我们的路由在他们的回调里面有依赖性,Laravel服务容器会自动注入它们:

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

必要的参数

Laravel的必要参数是路由中的参数, 当我们进行调用时, 不允许跳过这些参数. 否则就会出现错误:

Route::post("/gdpr/{userId}", GetGdprDataController.php");

现在在GetGdprDataController.php中,我们将可以直接访问$userId参数。

public function __invoke(int $userId) {
// Use the userId that we received…
}

一个路由可以接受任何数量的参数。它们被注入路由的回调/控制器中,基于它们被列出的顺序:

 // api.php
Route::post('/gdpr/{userId}/{userName}/{userAge}', GetGdprDataController.php);
// GetGdprDataController.php
public function __invoke(int $userId, string $userName, int $userAge) {
// Use the parameters…
}

可选参数

在这样的情况下,我们想在只有一个参数存在的情况下在路由上做一些事情,而不影响整个应用程序,我们可以添加一个可选参数。这些可选参数由附加在其上的 ? 表示:

 Route::get('/user/{age?}', function (int $age = null) {
if (!$age) Log::info("User doesn't have age set");
else Log::info("User's age is " . $age);
}
Route::get('/user/{name?}', function (int $name = "John Doe") {
Log::info("User's name is " . $name);
}

路由通配符

Laravel为我们提供了一种方法来过滤我们的可选或必需参数应该是什么样子.

比如我们想要一个用户ID的字符串. 我们可以使用 where 方法在路由层面进行验证。

where 方法接受参数的名称和将被应用于验证的regex规则。默认情况下,它接受第一个参数,但如果我们有很多参数,我们可以传递一个数组,以参数名称为键,以规则为值,Laravel将为我们解析所有参数:

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

我们可以更进一步,通过使用 Route facade上的 pattern 方法对我们应用程序中的所有路由进行验证。

 Route::pattern('id', '[0-9]+');

这将用这个regex表达式对每个 id 参数进行估值。一旦我们定义了它, 它就会自动应用于所有使用该参数名称的路由。

我们可以看到, Laravel在路由中使用 / 字符作为分隔符. 如果我们想在路由中使用它,我们必须使用 where regex明确允许它成为我们占位符的一部分。

 Route::get('/find/{query}', function ($query) {
//
})->where('query', , '.*');

唯一的缺点是,它只在最后一个路由段得到支持。

命名的路由

顾名思义,我们可以为路由命名,这使得我们可以方便地为特定的路由生成URL或重定向。

创建命名路由的一个简单方法是由 Route  facade上的 name 方法链提供的。每个路由的名字都应该是唯一的:

 Route::get('/', function () {
})->name("homepage");

路由组

路由组允许你在大量的路由中共享像中间件这样的路由属性,而不需要在每一个路由上重新定义。

中间件

为我们拥有的所有路由分配一个中间件,允许我们将它们组合在一个组中,首先使用 group 方法。需要考虑的一点是,中间件是按照应用到组中的顺序来执行的:

 Route:middleware(['AuthMiddleware', 'SessionMiddleware'])->group(function () {
Route::get('/', function() {} );
Route::post('/upload-picture', function () {} );
});

控制器

当一个组使用同一个控制器时,我们可以使用 controller 方法来定义该组内所有路由的共同控制器。现在我们必须指定路由将调用的方法。

 Route::controller(UserController::class)->group(function () {
Route::get('/orders/{userId}', 'getOrders');
Route::post('/order/{id}', 'postOrder');
});

子域路由

子域名称是添加到网站域名开头的一段额外信息。这允许网站将其特定功能的内容分开并组织起来,如网上商店、博客、演示文稿等与网站的其他部分分开。

我们的路由可以用来处理子域名的路由。我们可以抓住域和子域的一部分,在我们的控制器和路由中使用。在 Route facade上的 domain 方法的帮助下,我们可以将我们的路由放在一个单一的域下:

 Route::domain('{store}.enterprise.com')->group(function() {
Route::get('order/{id}', function (Account $account, string $id) {
// Your Code
}
});

前缀和名称前缀

每当我们有一组路由时, 我们可以利用Laravel提供的额外工具, 例如 Route 界面上的 prefix 和 name , 而不是一个一个的修改它们.

prefix 方法可以用来给组中的每个路由加上一个给定的URI,而 name 方法可以用来给每个路由的名字加上一个给定的字符串。

这使我们能够创建新的东西,如管理路由,而不需要修改每一个名称或前缀来识别它们:

 Route::name('admin.")->group(function() {
Route::prefix("admin")->group(function() {
Route::get('/get')->name('get');
Route::put('/put')->name(put');
Route::post('/post')->name('post');
});
});

现在,这些路由的URI将是 admin/getadmin/putadmin/post,以及名称 admin.getadmin.put, 和 admin.post

路由缓存

当把应用程序部署到生产服务器时, 一个好的Laravel开发者会利用Laravel的路由缓存的优势.

什么是路由缓存?

路由缓存减少了注册所有应用程序的路由所需的时间。

运行 php artisan route:cache ,会生成一个 Illuminate/Routing/RouteCollection 的实例,经过编码,序列化的输出被写入 bootstrap/cache.routes.php

现在任何其他请求都会加载这个缓存文件,如果它存在的话。因此,我们的应用程序不再需要解析和转换路由文件中的条目到 Illuminate/Routing/RouteCollection 中的 Illuminate/Routing/Route 对象。

为什么使用路由缓存很重要?

如果不使用Laravel提供的路由缓存功能, 你的应用程序有可能运行得更慢, 这可能反过来减少销售, 用户保留, 和对你品牌的信任.

根据你的项目的规模和路由的数量, 运行一个简单的路由缓存命令可以使你的应用程序的速度提高130%到500% – 一个巨大的收益,几乎没有任何努力。

小结

路由是后台开发的骨干。Laravel框架擅长于此, 它提供了一个定义和管理路由的详细方法.

开发确实可以为每个人所接受,并帮助加快一个应用程序,只是因为它是在Laravel中构建的。

你还遇到过哪些关于Laravel路由的技巧和提示? 请在评论区告诉我们!

评论留言