aivec / wordpress-router
WordPress 请求路由器。包含中间件、JWT 和 nonce 检查。
Requires
- aivec/response-handler: ^5.0
- firebase/php-jwt: ^5.0
- nikic/fast-route: ^1.3
Requires (Dev)
- aivec/codecept-docker: ^0.8.1
- aivec/phpcs-wp: ^2.0
- codeception/module-asserts: ^1.3
- codeception/module-cli: ^1.1
- codeception/module-db: ^1.1
- codeception/module-phpbrowser: ^1.0
- codeception/module-rest: ^2.0
- wp-cli/i18n-command: ^2.4
- dev-master
- v7.3.0
- v7.2.1
- v7.2.0
- v7.1.1
- v7.1.0
- v7.0.2
- v7.0.1
- v7.0.0
- v6.0.2
- v6.0.1
- v6.0.0
- v5.1.0
- v5.0.1
- v5.0.0
- v4.1.1
- v4.1.0
- v4.0.6
- v4.0.5
- v4.0.4
- v4.0.3
- v4.0.2
- v4.0.1
- v4.0.0
- v3.1.2
- v3.1.1
- v3.1.0
- v3.0.1
- v3.0.0
- v2.2.0
- v2.1.0
- v2.0.0
- v1.4.0
- v1.3.0
- v1.2.0
- v1.1.1
- v1.1.0
- v1.0.0
- dev-dependabot/composer/guzzlehttp/psr7-2.5.0
- dev-dependabot/composer/firebase/php-jwt-6.0.0
- dev-fix-roles
This package is auto-updated.
Last update: 2024-09-19 22:49:46 UTC
README
本包为 WordPress 提供了路由库,包含针对 WordPress 的特定包装,如 nonce 验证和用户角色检查。本包的核心使用 FastRoute,这是一个小型且简洁的路由解析器。《FastRoute》也是流行的微框架 Slim 所使用的路由解析器。
问题
WordPress 中的路由对插件作者来说是个头疼的问题。如果你采用 WordPress 传统方式通过 admin-ajax.php
注册 AJAX 处理器,它完全依赖于 $_POST
对象的键来解析路由。你可以使用 WordPress 的 REST API,但你无法控制路由何时解析。这对那些为其他插件创建扩展的开发者来说非常重要,因为这些开发者无法控制加载顺序。本包与 WordPress 的实现不同之处在于,它不提供 validate
和 sanitize
回调,而是选择使用通用中间件。
特性
该库提供了许多功能来简化路由的提供,以及一些可选的默认中间件。主要特性如下
- 基于角色的路由注册(编辑者、管理员等)
- 自动 nonce 验证
- URL 参数(非正则表达式 😁)
- 透传路由(非 AJAX 路由)
- 用于生成 HTML 表单的辅助函数
- JWT 路由注册
- JWT 设置页面用于自动生成密钥对
安装
使用 composer 安装
$ composer require aivec/wordpress-router
如果你计划在一个插件中使用此包,我们 强烈 建议使用 mozart 进行命名空间。如果不这样做,可能会出现难以调试的故障。 警告:已警告你。
使用指南
公开路由
公开路由是指不需要 nonce 验证的路由。公开路由任何人都可以从任何地方访问。
use Aivec\WordPress\Routing\Router; use Aivec\WordPress\Routing\WordPressRouteCollector; // First, we declare our routes by extending the `Router` class: class Routes extends Router { /** * This is where we define each route */ public function declareRoutes(WordPressRouteCollector $r) { $r->addPublicRoute('GET', '/hamburger', function () { return 'Here is a public hamburger.'; }); } } // Next, we instantiate the `Routes` class with a unique namespace and listen for requests $routes = new Routes('/mynamespace'); $routes->dispatcher->listen();
调用公开路由
你可以从命令行测试路由,如下所示
$ curl -X GET http://www.my-site.com/mynamespace/hamburger
'Here is a public hamburger.'
或者,你可以使用 jQuery
的 ajax
函数从加载到 WordPress 页面的脚本中发送请求
jQuery.ajax("http://www.my-site.com/mynamespace/hamburger", { success(data) { var response = JSON.parse(data); console.log(response); // Here is a public hamburger. }, });
私有路由
私有路由是指需要 nonce 验证的路由。
use Aivec\WordPress\Routing\Router; use Aivec\WordPress\Routing\WordPressRouteCollector; // First, extend the `Router` class: class Routes extends Router { /** * This is where we define each route */ public function declareRoutes(WordPressRouteCollector $r) { /** * `add` is the default way to register a route with nonce verification */ $r->add('POST', '/hamburger', function () { return 'Here is a private hamburger.'; }); } }
在声明了我们的路由之后,我们使用唯一的命名空间实例化 Routes
类。
这次,我们将 nonce 键和 nonce 名称作为第二个和第三个参数传入。
由于 nonce 处理需要 WordPress 核心函数,因此必须在核心函数加载之后实例化 Routes
类。你可以使用 init
钩子或任何其他适当的钩子来确保核心函数已加载。
$routes = null; add_action('init', function () use ($routes) { $routes = new Routes('/mynamespace', 'nonce-key', 'nonce-name'); $routes->dispatcher->listen(); });
调用私有路由
通常,私有路由是通过从 WordPress 网站上的 JavaScript 文件调用 AJAX 来调用的。为此,我们必须将 nonce 传递给我们要从中调用路由的脚本。
利用 wp_localize_script
,我们可以从 Routes
类中调用一个辅助方法来注入 nonce 变量。
add_action('wp_enqueue_scripts', function () use ($routes) { wp_enqueue_script( 'my-script', site_url() . '/wp-content/plugins/my-plugin/my-script.js', [], '1.0.0', false ); wp_localize_script('my-script', 'myvars', $routes->getScriptInjectionVariables()); });
现在,my-script.js
将包含我们需要的 nonce 变量以进行调用。
// my-script.js jQuery.ajax(`${myvars.endpoint}/hamburger`, { method: "POST", data: { [myvars.nonceKey]: myvars.nonce, }, success(data) { var response = JSON.parse(data); console.log(response); // Here is a private hamburger. }, });
URL 参数
花括号用于定义 URL 参数。
URL 参数将被解析,然后插入到 $args
变量中,该变量总是作为处理函数的 第一个 参数传递。
$r->add('POST', '/hamburger/{burgername}', function (array $args) { return 'Here is a ' . $args['burgername'] . ' hamburger.'; });
// my-script.js jQuery.ajax(`${myvars.endpoint}/hamburger/mushroom`, { method: "POST", data: { [myvars.nonceKey]: myvars.nonce, }, success(data) { var response = JSON.parse(data); console.log(response); // Here is a mushroom hamburger. }, });
您可以定义任意多的参数。
$r->add('POST', '/hamburger/{burgername}/{count}', function (array $args) { return 'Here are ' . $args['count'] . ' ' . $args['burgername'] . ' hamburgers.'; });
您还可以限制接受的参数类型,以及提供自己的模式以进行更精细的控制。
// Matches /user/42, but not /user/xyz $r->add('POST', '/user/{id:\d+}', .....); // Matches /user/foobar, but not /user/foo/bar $r->add('GET', '/user/{name}', .....); // Matches /user/foo/bar as well $r->add('GET', '/user/{name:.+}', .....);
路由定义有许多可能性。有关如何解析路由的详细信息,请参考这里。
表单数据
路由器期望以 application/x-www-form-urlencoded
的内容类型发送 POST
请求。表单数据作为 JSON 编码的字符串发送,作为请求体中 payload
键的值。
// $payload contains the decoded JSON key-value array $r->add('POST', '/hamburger', function (array $args, array $payload) { $ingredients = join(' and ', $payload['ingredients']); return 'I want ' . $ingredients . ' on my hamburger.'; });
// my-script.js jQuery.ajax(`${myvars.endpoint}/hamburger`, { method: "POST", data: { [myvars.nonceKey]: myvars.nonce, payload: JSON.stringify({ ingredients: ["pickles", "onion"], }), }, success(data) { var response = JSON.parse(data); console.log(response); // I want pickles and onion on my hamburger. }, });
让一切变得更简单
如我们所见,私有路由需要在 POST
请求体中存在 nonce 键值对。您可能已经注意到我们在那些例子中排除了 GET
请求。这是因为 GET
请求没有请求体内容,这意味着 nonce 变量必须作为 URL 查询参数设置。整个过程很繁琐,我们可以做得更好。
对于正在将 JavaScript 转译的人,我们建议使用 axios 和我们的 辅助库。这完全抽象了 nonce 处理和 JSON 编码,并在请求方法(GET
、POST
、PUT
等)中自动设置 nonce 变量。
以下是用这些库重写的 表单数据 示例。
// my-script.js import axios from "axios"; import { createRequestBody } from "@aivec/reqres-utils"; axios .post( `${myvars.endpoint}/hamburger`, createRequestBody(myvars, { ingredients: ["pickles", "onion"], }) ) .then(({ data }) => { console.log(data); });