处理RESTful url的PHP

use*_*487 7 php rest url mod-rewrite query-string

我无法掌握处理RESTful url的最合适方式.

我有这样的网址:

http://localhost/products 
http://localhost/products/123
http://localhost/products/123/color 
Run Code Online (Sandbox Code Playgroud)

本来:

http://localhost/index.php?handler=products&productID=123&additional=color
Run Code Online (Sandbox Code Playgroud)

至于现在我正在使用mod_rewrite:

RewriteRule ^([^/]*)([/])?([^/]*)?([/])?(.*)$ /index.php?handler=$1&productID=$3&additional=$5 [L,QSA]
Run Code Online (Sandbox Code Playgroud)

然后我把index.php中的请求拼凑起来,比如:

if ($_GET['handler'] == 'products' && isset($_GET['productID'])) {
   // get product by its id.
}
Run Code Online (Sandbox Code Playgroud)

我见过有人创建一个GET查询作为一个字符串,如:

if ($_GET['handler'] == 'products/123/color')
Run Code Online (Sandbox Code Playgroud)

那么,您是否使用正则表达式从查询字符串中获取值?

这是处理这些网址的更好方法吗?这些不同方法的优缺点是什么?有更好的方法吗?

fre*_*dev 6

您可以使用不同的方法而不是匹配所有参数使用apache重写您可以使用preg_match匹配PHP中的完整请求路径.应用PHP正则表达式将所有参数移动到$args数组中.

$request_uri = @parse_url($_SERVER['REQUEST_URI']);
$path = $request_uri['path'];
$selectors = array(
     "@^/products/(?P<productId>[^/]+)|/?$@" => 
            (array( "GET" => "getProductById", "DELETE" => "deleteProductById" ))
);

foreach ($selectors as $regex => $funcs) {
    if (preg_match($regex, $path, $args)) {
        $method = $_SERVER['REQUEST_METHOD'];
        if (isset($funcs[$method])) {
            // here the request is handled and the correct method called. 
            echo "calling ".$funcs[$method]." for ".print_r($args);
            $output = $funcs[$method]($args);
            // handling the output...
        }
        break;
     }
}
Run Code Online (Sandbox Code Playgroud)

这种方法有很多好处:

  • 您没有为正在开发的每个REST服务重写.我喜欢重写,但在这种情况下,你需要很多自由,并且使用重写时,每次部署/保存新服务时都需要更改Apache配置.
  • 您可以为所有传入请求设置一个PHP前端类.前端将所有请求分派给正确的控制器.
  • 您可以迭代地将正则表达式数组应用于传入请求,然后相应地调用正确的函数或类控制器/方法以成功匹配
  • 最后,控制器被实例化以处理请求,在这里您可以检查用于http请求的HTTP方法


da5*_*5id 6

这个 .htaccess 条目会将除现有文件之外的所有内容发送到 index.php:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php
Run Code Online (Sandbox Code Playgroud)

然后你可以做这样的事情来将 url 转换为数组:

$url_array = explode('/', $_SERVER['REQUEST_URI']);
array_shift($url_array); // remove first value as it's empty
array_pop($url_array); // remove last value as it's empty
Run Code Online (Sandbox Code Playgroud)

然后你可以这样使用开关:

switch ($url_array[0]) {

    case 'products' :
        // further products switch on url_array[1] if applicable
        break;

    case 'foo' :
        // whatever
        break;

    default :
        // home/login/etc
        break;

}
Run Code Online (Sandbox Code Playgroud)

反正我一般都是这么干的。