[扩展推荐] Ziggy:在 JavaScript 中使用 Laravel 的命名路由
「译者注」 一句话来描述这个扩展的作用:可以解决在 JavaScript 中无法方便设置 URL 的问题。例如
question/{question}/edit
这种结构。「译者注」 这篇文章虽然时间比较早,是2017年的了。但该扩展还是很实用的,而且也在一直更新,增加了一些新功能,比如白名单、黑名单等安全性相关更新,我会补充到文章末尾。
我的 JavaScript 中充满了 [axios
] (https://github.com/mzabriskie/axios) 调用,这些调用是对 Laravel 应用中 API 接口地址的硬编码,当需要添加参数或者后端接口地址变更时会非常痛苦。
这就是为什么在 Laravel 中我们有 命名路由,以及为什么我们没有在 Blade 模板中硬编码 URL 的原因。通过抽象化我们的使用代码来了解路由的准确 URL 的需求,我们能够编写更多健壮性的代码-并避免了很多因为路由变更而导致的「查找和替换」。
我们希望在 JavaScript 中可以获得与 Laravel 应用程序相同的体验,这就是我们建造 Ziggy 的原因。
Basic Usage
安装 Ziggy
1、使用 Composer 进行安装: composer require tightenco/ziggy
2、如果你的 Laravel 版本小于 5.5,那么需要将Tightenco\Ziggy\ZiggyServiceProvider::class
添加到 config/app.php
文件的 providers
数组中。
3、在加载主应用程序 JavaScript 之前,将我们的自定义 Blade 指令 @routes
放到应用程序的 Blade 布局文件中,一般是放在 layout.blade.php
文件中。
layout.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
</head>
<body>
<div class="app">
</div>
// 自定义 Blade 指令
@routes
<script src="{{ mix('js/app.js') }}"></script>
</body>
</html>
Blade 指令将替换为 <script>
标签,在 Ziggy.namedRoutes 的 JavaScript 对象中,包含了路由信息。
该指令还包含一个名为 route()
的 JavaScript 方法,功能与 Laravel 的 route()
辅助方法非常相似。
routes/api.php
// 没有路由名称,所以不会输出在前端
Route::get('/', 'HomeController');
// 有路由名称,会输出在前端
Route::group(['as' => 'posts.'], function () {
Route::get('/', 'PostsController@index')
->name('index');
Route::get('/{post}', 'PostsController@show')
->name('show');
Route::post('/', 'PostsController@store')
->name('store');
});
Route::get('/{post}/comments', 'PostCommentsController@index')
->name('post-comments.index');
这事 @routes
标签输出的实际代码(为了方便显示,只显示了一个路由信息):
JavaScript 内容
<script>
var namedRoutes = JSON.parse(
'{"posts.index":{"uri":"posts","methods":["GET","HEAD"]}}'
);
// 可以在下面使用 route() 方法来获取 URL
</script>
就如你看到的一样,我们增加了 window.namedRoutes
对象,可以随时访问它。它是一个包含一系列数据的对象,其中包括路由名称、提交方法等,它使用路由的名称作为键值,因此可以直接在代码中这么使用:var routeObject = window.namedRoutes['posts.index'];
当然,推荐你使用 route()
辅助方法,它与 Laravel 框架的 route()
作用非常相似,会更加方便:
// 实际值为: /posts
var routeUrl = route('posts.index');
// 实际值为:/posts/1337
var routeUrl = route('posts.show', {post: 1337});
这是背后运行的真实样子:
// Returns results from /posts
return axios.get(route('posts.index'))
.then((response) => {
return response.data;
});
// Returns results from /posts/1
return axios.get(route('posts.show', {post: postId}))
.then((response) => {
return response.data;
});
route()
辅助方法有 2 个参数
- 路由名称(必填)
- 路由参数(可选)
例如 posts.show
路由信息需要一个 post
参数,因为我们将 {post: postId}
作为参数传递给 route()
辅助方法。
结论
将 Ziggy 扩展包引入 Laravel 并将 @routes
指令放入全局模板后,你将考验使用 route()
辅助方法,它与 Laravel 的辅助方法一样方便。最重要的是这将 Laravel 的路由信息与 JavaScript 代码关联起来了,避免了因为修改路由信息而批量查找、替换 JavaScript 代码的情况。
「译者注」 目前最新的扩展包已经支持了对路由信息进行过滤的功能,可以设置黑名单或白名单的方式,提升了一定的安全性,我可不想把项目的所有路由信息暴露给你看。
如何过滤路由信息
默认会将所有信息都输出在前端,如果想控制路由信息的显示,可以使用白名单或者黑名单的方式:
- 在 config 目录下新建 ziggy.php 文件
- 设置 whitelist 或 blacklist 数组
<?php
return [
// 'whitelist' => ['home', 'api.*'],
'blacklist' => ['debugbar.*', 'admin.*'],
];
为了安全性,对 admin 以及 debugbar 相关的路由信息屏蔽输出,这样前端的 JavaScript 数组中就看不到,当然你也无法在 JavaScript 中使用 route()
辅助方法了。
还可以有其他的设置方式,具体可以取项目主页瞧一下。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: