sergiosgc / rest-router
基于文件系统的请求路由器,适用于了解HTTP动词的应用程序(RESTful)
Requires
- php: >=7.0.0
- willdurand/negotiation: 3.*
This package is auto-updated.
Last update: 2024-09-11 18:51:09 UTC
README
基于文件系统的请求路由器,适用于了解HTTP动词的应用程序(RESTful)
目标
通常PHP请求路由模式是从请求URI中获取脚本文件名,可能是在添加 index.php
后。此路由器遵循相同的逻辑,并在RESTful路径上向上一步。它使用请求HTTP动词(GET
、POST
、PUT
、...)来确定将处理请求的文件系统路径中的正确脚本。
假设一个应用程序存储在文档根目录 /srv/www/myapp
下的应用程序接收三个请求
- A GET to
/customer/
- A POST to
/customer/
- A PUT to
/customer/10
在典型的PHP路由中,前两个请求将由 /srv/www/myapp/customer/index.php
处理,而第三个请求将需要在Web服务器层进行请求重写
使用此路由器,请求将由
/srv/www/myapp/customer/get.php
/srv/www/myapp/customer/post.php
/srv/www/myapp/customer/put.php
(提取客户ID是可能的,并在本readme中介绍)
这简化了RESTful应用程序的开发,同时利用应用程序目录结构来映射URL空间。
安装
最简单的方法是使用Composer安装和使用。在你的composer.json中
# composer.json
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/sergiosgc/composer-fs-rest-router.git"
}
],
"require": {
"sergiosgc/rest-router": "dev-master"
}
}
然后发出 composer update
或 composer install
。
现在,在您的文档根目录中,创建一个名为index.php的捕获所有脚本
<?php
require_once('vendor/autoload.php');
(new \sergiosgc\router\Rest())->route();
并配置您的Web服务器将所有vhost请求路由到此index.php。例如,在nginx中,vhost文件可能如下所示
server {
listen 80;
root /srv/www/myapp;
index /index.php;
location / {
try_files $uri /index.php?$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
include fastcgi_params;
}
}
基本用法
只需为您的RESTful对象创建目录。例如,要处理对 /customer/
的请求,创建一个目录 /srv/www/myapp/customer/
。然后,为要处理的每个方法创建一个脚本文件
post.php
用于POST方法(创建)get.php
用于GET/HEAD方法(读取)head.php
用于HEAD方法put.php
用于PUT方法(更新)delete.php
用于DELETE方法(删除)
如果 head.php
不存在,路由器将回退到 get.php
。任何方法都接受;文件名应该是小写的动词名称,后面跟 .php
。
从URL中提取参数
路由器将设置以下两个变量
$_SERVER['ROUTER_PATHBOUND_REQUEST_URI']
:匹配文件系统目录的URL部分$_SERVER['ROUTER_PATHBOUND_SCRIPT_FILENAME']
:从$_SERVER['ROUTER_PATHBOUND_REQUEST_URI']
获得的脚本文件名
$_SERVER['ROUTER_PATHBOUND_REQUEST_URI'] 是从 $_SERVER['REQUEST_URI'] 中消耗掉匹配路径中找到的正则表达式文件的成功匹配的结果。它匹配文档根目录中存在的目录。
当使用美化后的URL时,您可以从请求URL的无绑定部分提取额外数据。在上面的示例中,由 /srv/www/myapp/customer/put.php
处理的PUT到 /customer/10
将使 10
成为 $_SERVER['ROUTER_UNBOUND_REQUEST_URI']
的值。
对于更复杂的URL,您可以使用正则表达式来提取参数。在与动词处理PHP脚本相同的目录中,放下一个带有命名组的正则表达式。让我们假设URL /customer/10/20
被解释为从minid 10到maxid 20的客户。在 /srv/www/myapp/customer/get.php
旁边创建 /srv/www/myapp/customer/get.regex
,内容如下
_^(?<minid>[0-9]+)/(?<maxid>[0-9]+)_
请求路由器将使用此正则表达式来
- 匹配无绑定请求URI并提取参数minid和maxid。这些将填充
$_REQUEST
- 验证无绑定URI是否有效(否则抛出404错误)
URL子树
如果您希望脚本自动处理该URL树节点及其下所有请求,可以使用消耗剩余URI的正则表达式来实现。
例如,一个脚本 /srv/www/myapp/customer/order/get.php
可以处理 /customer/order/
和 /customer/order/return/
这样的URL。要实现这一点,可以在 /srv/www/myapp/customer/order/get.regex
中放置一个正则表达式,如下所示:
_^(?<remaining>.*)$_
路径中最具体的脚本将被使用。例如,如果存在这两个脚本:/srv/www/myapp/customer/order/get.php
和 /srv/www/myapp/customer/get.php
,那么URL /customer/order/return/
将由 /srv/www/myapp/customer/order/get.php
处理。
HTML动词限制的解决方案
虽然HTTP定义了一组丰富的方法,但HTML实际上只允许GET和POST。为了解决这个问题,在HTML中,您可以在任何请求中使用x-verb
参数来覆盖HTTP动词。例如,当点击链接 /customer/12?x-verb=DELETE
时,在浏览器中会发出一个GET HTTP请求,但路由器会将其处理为DELETE请求。
调试
通过启用$debug静态变量,您可以获取路由器对URL匹配的调试信息,而不是正常的响应。这可以在上述提到的catch-all脚本中轻松实现,如下所示:
<?php
require_once('vendor/autoload.php');
\sergiosgc\router\Rest::$debug = true;
(new \sergiosgc\router\Rest())->route();