简体   繁体   English

处理RESTful url的PHP

[英]Handling RESTful url's PHP

I'm having trouble grasping what would be the most proper way of handling RESTful url's. 我无法掌握处理RESTful url的最合适方式。

I'm having url's like these: 我有这样的网址:

http://localhost/products 
http://localhost/products/123
http://localhost/products/123/color 

Originally: 本来:

http://localhost/index.php?handler=products&productID=123&additional=color

As for now I'm using mod_rewrite: 至于现在我正在使用mod_rewrite:

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

And then I'm puzzling together the requests in index.php, something like: 然后我把index.php中的请求拼凑起来,比如:

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

I've seen some creating a GET-query as one string like: 我见过一些创建GET查询作为一个字符串,如:

if ($_GET['handler'] == 'products/123/color')

Then, do you for example use regular expressions to get the values out of the query-string? 那么,您是否使用正则表达式从查询字符串中获取值?

Is this a better approach to handle these url's? 这是处理这些网址的更好方法吗? What are the pros and cons with these different approaches? 这些不同方法的优缺点是什么? Is there some better way? 有更好的方法吗?

You could use a different approach instead of match all parameters using apache rewrites you could match the full request path in PHP using preg_match. 您可以使用不同的方法而不是匹配所有参数使用apache重写您可以使用preg_match匹配PHP中的完整请求路径。 Applying the PHP regular expression all the parameters will be moved into the $args array. 应用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;
     }
}

This approach has many benefits: 这种方法有很多好处:

  • You don't have a rewrite for each REST service you're developing. 您没有为正在开发的每个REST服务重写。 I like rewrites, but in this case you need a lot of freedom, and using rewrites you need to change Apache config every time you deploy/mantain a new service. 我喜欢重写,但在这种情况下你需要很多自由,并且使用重写时,每次部署/保存新服务时都需要更改Apache配置。
  • You can have a single PHP frontend class for all incoming requests. 您可以为所有传入请求设置一个PHP前端类。 The frontend dispatch all the requests to the correct controller. 前端将所有请求分派给正确的控制器。
  • You can apply iteratively an array of regular expression to the incoming requests and then call the correct function or class controller/method accordingly to the successful match 您可以迭代地将正则表达式数组应用于传入请求,然后相应地调用正确的函数或类控制器/方法以成功匹配
  • When finally the controller is instantiated to handle the request, here you can check the HTTP method used into http request 最后,控制器被实例化以处理请求,在这里您可以检查用于http请求的HTTP方法

This .htaccess entry will send everything except existing files to index.php: 此.htaccess条目将除现有文件之外的所有内容发送到index.php:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php

Then you can do something like this to convert the url into an array: 然后你可以做这样的事情将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

Then you can use a switch thusly: 然后你就可以使用一个开关:

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;

}

That's what I generally do anyway. 无论如何,这就是我一般所做的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM