sformisano / jetrouter

此包的最新版本(v1.0)没有可用的许可证信息。

直观的 WordPress 路由器。

v1.0 2017-11-14 21:16 UTC

This package is not auto-updated.

Last update: 2024-09-29 06:02:26 UTC


README

Build Status Code Climate

此 WordPress 插件在 WordPress 标准路由系统之上添加了一个基于正则表达式的路由器。通过此路由器声明的任何路由都将优先于标准 WordPress URL。

安装

下载 zip 文件

通过 WordPress 插件页面下载

您可以访问 WordPress 插件页面 并在那里下载最新的插件版本。

通过 GitHub 仓库发布页面下载

您还可以从该仓库的 发布页面 获取最新版本。

Composer

如果您使用 Composer 进行正确的依赖关系管理(如果您对将 WordPress 作为 12 因素应用程序运行感兴趣,请查看出色的 Bedrock 项目),安装 JetRouter 非常简单。

通过 WordPress Packagist(更简单、更好)

WordPress Packagist 是一个网站,它每小时扫描 WordPress Subversion 仓库中的插件和主题,然后将它们镜像为 Composer 仓库。

搜索 "jetrouter"(这里是 搜索结果),单击记录 "版本" 列中的最新版本,您将获得可在 composer.json 文件的 require 属性中粘贴的代码。

它看起来可能像这样

"wpackagist-plugin/jetrouter": "0.1.2.1"

请注意:我没有时间验证这一点,但即使没有使用 Bedrock WordPress 模板,wpackagist 包也应自动安装到插件目录(这是您想要的),而不是默认的 composer vendor 目录。如果情况并非如此,请参考下文中的 通过 GitHub 发布的 Composer 部分,了解如何告诉 composer 将您的 WordPress 插件安装在哪里。

通过 GitHub 发布的 Composer

将此包添加到您的 composer json 定义中的 "repositories" 属性(确保发布版本是您想要安装的版本)

{
  "repositories": [
    {
      "type": "package",
      "package": {
        "name": "jetrouter",
        "type": "wordpress-plugin",
        "version": "0.1.2.1",
        "dist": {
          "type": "zip",
          "url": "https://github.com/sformisano/jetrouter/releases/download/v0.1.2/jetrouter-v0.1.2.1.zip",
          "reference": "v0.1.2.1"
        },
        "autoload": {
          "classmap": ["."]
        }
      }
    }
  ]
}

完成此操作后,将 JetRouter 添加到 composer require 属性中(版本必须与包版本匹配)

{
  "require":{
    "jetrouter": "0.1.2.1"
  }
}

最后,请确保指定正确的路径,我们在上面的定义中将 JetRouter 包指定为 "wordpress-plugin" 类型(注意:如果您正在使用 Bedrock,这已经解决了)。

{
  "extra": {
    "installer-paths": {
      "path/to/your/wordpress/plugins-directory/{$name}/": ["type:wordpress-plugin"],
    }
  }
}

从您的 composer 目录运行 composer update 并继续下一步!

用法

初始化 & 配置

在您的主题的 functions.php 文件或插件中的某个位置

// Import the JetRouter
use JetRouter\Router;
  
// Router config
$config = [];
  
// Create the router instance
$r = Router::create($config);

可用的路由器配置属性

  • 命名空间:如果定义了,命名空间前缀所有路由,例如,如果您将命名空间设置为“my-api”,然后定义路由为“comments/published”,实际的端点将是“/my-api/comments/published/”。
  • outputFormat:确定路由处理程序的输出格式。可用值:autojsonhtml

路由器自动将自己挂钩到WordPress,因此一旦您创建了适合您需求的路由器实例,剩下的工作就是添加路由。之后,路由器就准备好处理请求了。

关于命名空间的技巧

如果您使用JetRouter构建json/data API,或者您不介意在URL前有命名空间,那么拥有一个命名空间将加快标准WordPress请求的速度,尤其是如果您有多个动态路由。

这是因为,如果路由器有命名空间,但HTTP请求的路径不以该命名空间开头(就像所有WordPress URL那样),路由器甚至不会尝试分发请求。

另一方面,没有命名空间的情况下,路由器将尝试分发所有请求,每次都构建动态路由数组。(注意:缓存生成的动态路由在我的待办事项列表中。)

添加路由

基础

添加路由的基本方法是addMethod。示例

$r->addRoute('GET', 'some/resource/path', 'the_route_name', function(){
  // the callback fired when a request matches this route
});

addRoute方法为每个HTTP方法(get、post、put、patch、delete、head、options)提供了别名。示例

$r->get(‘users/new’, ‘route_name’, function(){
  // new user form view
});

$r->post('users', 'create_user', function(){
  // create user in database
});

动态路由

使用花括号来突出参数,然后将其声明为回调函数的参数,路由器将处理其他所有事情。示例

$r->get('users/{username}', 'get_user_by_username', function($username){
  echo "Welcome back, $username!";
});

$->get('schools/{school}/students/{year}', 'get_school_students_by_year', function($school, $year){
  echo "Welcome, $school students of $year!";
});

参数正则表达式

默认情况下,所有参数都会与一个非常宽容的正则表达式匹配

/**
  * One or more characters that is not a '/'
  */
  const DEFAULT_PARAM_VALUE_REGEX = '[^/]+';

您可以通过在参数名称后添加冒号,并在其后添加正则表达式来使用您自己的正则表达式。示例

$r->get('schools/{school}/students/{year:[0-9]+}', 'get_school_students_by_year', function($school, $year){
  // If $year is not an integer an exception will be thrown
});

您还可以使用以下正则表达式快捷方式以方便使用

private $regexShortcuts = [
  ':i}' => ':[0-9]+}',           // integer
  ':a}' => ':[a-zA-Z0-9]+}',     // alphanumeric
  ':s}' => ':[a-zA-Z0-9_\-\.]+}' // alphanumeric, "_", "-" and ".""
];

例如,如果我们想使用:i快捷方式以相同的方式编写相同的get_school_students_by_year路由,我们会这样做

$r->get('schools/{school}/students/{year:i}', 'get_school_students_by_year', function($school, $year){
  // If $year is not an integer an exception will be thrown
});

可选参数

您可以通过在关闭花括号后添加问号来使一个参数成为可选的。示例

$r->get('schools/{school}/students/{year}?’, 'get_school_students_by_year', function($school, $year){
  // $year can be empty!
});

您可以使所有参数成为可选的,即使它们不是路由的最后一个部分。示例

$r->get('files/{filter_name}?/{filter_value}?/latest', 'get_latest_files', function($filter_name, $filter_value){
  // get files and work with filters if they have a value
});

以下所有示例请求都会与上面定义的路由匹配

'/files/latest'
'/files/type/pdf/latest'
'/files/author/sformisano/latest'

这不一定是有可选参数的最佳用法。这里提供的示例只是为了说明,如果您有有效的用例,JetRouter将允许您以这种方式设置路由。

反向路由

为了简单起见,反向路由是通过相同的路由器对象完成的。

给定这个简单的示例路由

$r->addRoute('GET', 'posts/popular', 'popular_posts', function(){});

要打印出完整路径,您使用thePath方法

$r->thePath('popular_posts'); // prints /posts/popular/

您也可以通过使用getThePath方法来获取返回值,而不是打印出来(试图遵循一些WordPress约定)

$r->getThePath('popular_posts'); // returns /posts/popular/

动态路由反向路由

动态路由的工作方式完全相同,您只需在路由名称后按定义顺序传递参数值。

例如,给定此路由

$r->get('schools/{school}/students/{year}?’, 'get_school_students_by_year', function($school, $year){
});

这是您打印出此路由完整路径的方式

$r->thePath('get_school_students_by_year', 'caltech', 2005); // prints  /schools/caltech/students/2005/

由于最后一个参数是可选的,您可以简单地省略它

$r->thePath('get_school_students_by_year', 'mit'); // prints  /schools/mit/students/

如果您需要省略的可选参数不是最后一个参数,您只需传递null作为值,它将被忽略。示例

$r->get('{school}?/students/{year}’, 'get_students', function($school, $year){
});

$r->thePath('get_students', null, 1999); // prints /students/1999/

我更喜欢这种方法,而不是更常见的关联数组参数,因为它使一切更简单(在大多数情况下输入更少)并且更明确(缺失的可选参数仍然被定义为null,因此形式参数和参数之间有一对一匹配)。

处理器的 respond_to 功能

如果您曾经玩过Ruby on Rails,您可能熟悉respond_to和respond_with块。这个respond_to功能是对那种巧妙处理不同请求类型和不同行为的基本、简单模仿。

如果您从未尝试过Rails,让我用一个例子来简化这个过程

您创建了一个公开的注册表单,该表单提交到JetRouter创建的create_user端点。您肯定希望这个表单可以通过ajax工作,但您是少数几个仍然关心优雅降级的开发者之一,所以您不只想将outputFormat配置参数设置为json并执行类似return $data;的操作。您需要能够接收ajax请求的json数据,同时在标准、同步请求中执行其他操作(例如重定向、错误模式下的视图加载等)。

技术上,您可以手动检查$_SERVER['HTTP_X_REQUESTED_WITH']并编写一些与该检查相关的条件代码,但谁愿意为每个端点都做这种手动劳动呢?

JetRouter的respond_to功能可以解决这些问题!您只需要将outputFormat配置参数设置为auto,并让您的路由处理程序返回一个符合以下格式的数组

// endpoint doing stuff up here

return [ 'respond_to' => [
  'json' => $output // this is whatever came out of this endpoint, to be returned as json!,
  'html' => function(){
    // this callback will run if this the route handler is dispatching a standard, synchronous request
    // do something here, then maybe redirect with wp_redirect or whatever else!
  }
] ];

提示:在请求路径后附加?json将强制输出json。

我为什么构建JetRouter

  • 我希望有一个快速、易于设置且API最小的路由器。JetRouter只需一行代码($r = Router::create();)即可设置,所有功能都通过该对象提供。

  • 我需要一些其他功能,这些功能在我熟悉的任何小型足迹php路由器中都没有提供,包括以下提到的那些。

  • 我所了解的路由器,即使是以下提到的那些,都是为了用作网站/webapp的核心路由系统。这并不意味着它们最适合用作WordPress额外路由层的使用场景,例如,如果找不到路由或者路径匹配但请求的http方法不同,它们将抛出异常。因为这个路由器是WordPress之上的一个额外层,所以在大多数这些场景中需要静默失败并控制权返回给WordPress。WordPress然后可以处理那些匹配的请求,返回404或执行其应执行的其他操作。

  • 最后,构建这个看起来是一种很好的方式来重新审视PCRE,这已经有很多年没有使用了。

致谢

  • 这个路由器实现了Nikita Popov的基于组位置的非分块正则表达式匹配方法,用于闪电般的路由。通过阅读Nikita自己的这篇优秀的文章了解更多信息。

  • Joe Green和他的phroute项目(也是基于Nikita的工作)应该感谢

    • 用于捕获动态路由参数的正则表达式
    • 正则表达式快捷方式(一个简单而非常优雅的想法)
    • 可选参数和反向路由实现的基本内容

去看看这两位作者和他们的项目,他们都很棒。