在PHP中,我希望能够全局访问PUT
和DELETE
个vars,类似于全局访问GET
和POST
vars的方式。我最初考虑将数据分别添加到全局命名空间中的$_PUT
和$_DELETE
,但后来我意识到每个请求的数据都存储在消息体中,所以没有办法超过来自POST
,PUT
或DELETE
请求的一个数据集。
$_POST
变量的副作用?即。 str_parse( file_get_contents( 'php://input' ), $_POST );
我是愚蠢的,还是有更好的方式来访问PUT
和DELETE
数据?
编辑以澄清我的想法:
我非常清楚$_POST
中数据的来源,事实上我在前面的问题中提到过它。如果向服务器发送HTTP POST请求,则数据将存储在php://input
中。如果向服务器发送HTTP PUT或DELETE请求,则数据将存储在完全相同的位置,这意味着$_POST
将为空(尽管数据可用,因此没有数据POSTed
。
另一方面,GET
请求通过查询字符串传递。这允许同时传递$_POST
和$_GET
变量。同时传递POST
和PUT or DELETE
变量不。
如果我在$_POST
和php://input
请求上覆盖PUT
DELETE
,则不会丢失数据。
添加的替代选择:
global $_PUT;
global $_DELETE;
到函数的开头似乎很愚蠢,因为我一次只能使用一个 。
我的第一个问题,即我真正想要回答的问题,是关于覆盖$_POST
存在哪些副作用或问题。我不可能成为第一个尝试傻事的人:
$_POST['foo'] = 'bar';
我只是担心如果我做了类似的事情,它可能不会在范围内保留。
答案 0 :(得分:15)
你会在整个互联网上看到这个被称为“坏习惯”的东西,但如果你真的进入为什么这是“坏习惯”,那么答案就会变得模糊。最具体的原因是“公共汽车撞击”的场景经常被大肆渲染 - 如果项目交给新的开发人员怎么办?
撇开手(毕竟你可以发表评论),确实没有令人信服的理由不这样做,但同样,没有令人信服的理由 也做到了。如果您想要全局,为什么不将值放在$_SESSION
键中?或者制作一个全局变量?或者创建一个静态类来访问PUT / DELETE值?使用所有其他可选方法,我认为覆盖$_POST
,虽然它不会使您的服务器爆炸,但最有可能让您头疼。
我将这个小静态类放在一起,你需要在依赖它之前测试它。使用:
//To check if this is a rest request:
Rest::isRest();
//To get a parameter from PUT
$put_var = Rest::put('keyname', false);
//To get a parameter from DELETE
$dele_var = Rest::delete('keyname', false);
class Rest {
static private $put = false;
static private $delete = false;
static private $is_rest = false;
function __construct() {
self::$is_rest = true;
switch ($_SERVER['REQUEST_METHOD']) {
case 'PUT':
parse_str(self::getVars(), self::$put);
break;
case 'DELETE':
parse_str(self::getVars(), self::$delete);
break;
default:
self::$is_rest = false;
}
}
private static function getVars() {
if (strlen(trim($vars = file_get_contents('php://input'))) === 0)
$vars = false;
return $vars;
}
public static function delete($key=false, $default=false) {
if (self::$is_rest !== true)
return $default;
if (is_array(self::$delete) && array_key_exists($key, self::$delete))
return self::$delete[$key];
return $default;
}
public static function put($key=false, $default=false) {
if (self::$is_rest !== true)
return $default;
if (is_array(self::$put) && array_key_exists($key, self::$put))
return self::$put[$key];
return $default;
}
public static function isRest() {
return self::$is_rest;
}
}
答案 1 :(得分:4)
离开Post并获取原样。它不应该被修改,因为它只是为了阅读目的。创建$ _PUT和$ _DELETE globals:
// globals
$_DELETE = array ();
$_PUT = array ();
switch ( $_SERVER['REQUEST_METHOD'] ) {
case !strcasecmp($_SERVER['REQUEST_METHOD'],'DELETE'):
parse_str( file_get_contents( 'php://input' ), $_DELETE );
break;
case !strcasecmp($_SERVER['REQUEST_METHOD'],'PUT'):
parse_str( file_get_contents( 'php://input' ), $_PUT );
break;
}
未经测试,但您应该明白这一点。几个星期前我一直在寻找一个休息框架,并决定使用python。休息(http://www.recessframework.org/)听起来很有希望
答案 2 :(得分:3)
您不应直接修改$_POST
,因为它代表来自客户端的值。将其视为只读,并对用户定义的变量进行任何修改。
作为访问PUT和DELETE数据的后续工作,目前PHP内置的超级全局没有直接访问这些数据。由于数据是文件数据,这可能相当大,因此在典型的赋值语句$variable = $_PUT['file'];
中读取整个文件内容的有用性和效率值得怀疑。相反,它应该以块的形式阅读。因此,使用情况与从任何其他文件输入资源读取一致。
更多关于PUT的信息:
http://php.net/manual/en/features.file-upload.put-method.php
答案 3 :(得分:-1)
如果您创建“请求”对象,那么无论请求是通过HTTP,命令行还是通过HTML5 Web套接字,您都可以使用统一的方式来访问请求数据。然后,您可以在全局范围内访问请求对象,或将其作为参数传递给所需的函数或方法。
理想情况下,您可以在静态或全局变量中存储独立于请求的数据,例如:无论请求如何都是“静态”的设置,以及可由业务逻辑使用的本地变量或对象中特定于请求的数据。例如,如果您有一个Web套接字服务器,那么在单个PHP进程中处理多个请求对象会更容易。以下是一个可能有用的示例:
$headers = getallheaders();
$query = parse_str($_SERVER['QUERY_STRING']);
$data = file_get_contents('php://input');
if(strpos($headers['Content-Type'],'application/x-www-form-urlencoded') !== false)
{
$data = parse_str($data);
}
elseif(strpos($headers['Content-Type'],'application/json') !== false)
{
$data = json_decode($data);
}
elseif(strpos($headers['Content-Type'],'application/soap+xml') !== false)
{
$data = // parse soap
}
elseif(strpos($headers['Content-Type'],'application/xml') !== false)
{
$data = // parse xml
}
// else ...
$request = new Request($_SERVER['REQUEST_METHOD'],$data,$query);
// example business logic
$method = $request->get_request_method();
$obj = new BlogPost();
if($method == 'GET')
{
$obj->id($request->get_query('id'));
$obj->load();
}
elseif($method == 'PUT')
{
$obj->id($request->get_query('id'));
$obj->title($request->get_data('title'));
$obj->body($request->get_data('body'));
$obj->save();
}
elseif($method == 'POST')
{
$obj->title($request->get_data('title'));
$obj->body($request->get_data('body'));
$obj->save();
}
elseif($method == 'DELETE')
{
$obj->id($request->get_query('id'));
$obj->wipe();
}
无论是PUT,POST,PATCH还是DELETE,HTTP请求中只有一个数据体,因此您的应用程序不需要复杂的$ request对象。请求对象可以使您的控制器(如果您使用的是MVC)非常简单。