问答中心分类: PHPPHP“php://input“vs$_帖子
0
匿名用户 提问 19小时 前

我已被指示使用该方法php://input而不是$_POST当与来自JQuery的Ajax请求交互时。我不明白的是,使用这种方法与全局方法相比有什么好处$_POST$_GET.

4 Answers
0
Anthony Rutledge 回答 19小时 前

首先,了解PHP的基本情况。
PHP的设计目的并不是显式地为您提供一个纯粹的REST(GET、POST、PUT、PATCH、DELETE)接口来处理HTTP请求.
然而$_SERVER,$_COOKIE,$_POST,$_GET$_FILES 超球,以及函数filter_input_array()对于普通人/外行的需求非常有用。
最大的隐藏优势$_POST(和$_GET)你的输入数据是PHP自动解码的url. 您甚至从未想过必须这样做,尤其是对于标准中的查询字符串参数GET请求或HTTP正文数据随POST要求
其他HTTP请求方法
那些研究底层HTTP协议及其各种请求方法的人逐渐了解到,有许多HTTP请求方法,包括经常引用的PUT,PATCH(未在谷歌的Apigee中使用),以及DELETE.
在PHP中,没有超全局函数或输入过滤器函数来获取HTTP请求体数据POST未使用。罗伊·菲尔丁的弟子们要做什么
然而,你会学到更多。。。
话虽如此,随着你对PHP编程知识的提高,并希望使用JavaScript的XmlHttpRequest对象(有些是jQuery),您会看到这个方案的局限性。
$_POST限制您在HTTP中使用两种媒体类型Content-Type标题:

  1. application/x-www-form-urlencoded
  2. multipart/form-data

因此,如果您想将数据值发送到服务器上的PHP,并将其显示在$_POST超全局,那么你必须URL编码它位于客户端,并以键/值对的形式发送所述数据——这对于新手来说是一个不方便的步骤(尤其是当试图弄清楚URL的不同部分是否需要不同形式的URL编码时:正常、原始等)。
对于所有jQuery用户来说$.ajax()方法是在将JSON传输到服务器之前,将其转换为URL编码的键/值对。您可以通过设置processData: false. 只需阅读$.ajax()文档,并且不要忘记在内容类型标头中发送正确的媒体类型。
php://input但是
即使你使用php://input而不是$_POST对于您的HTTPPOST请求身体数据,它会不工作使用HTTPContent-Type属于multipart/form-data这是当您希望允许文件上载时在HTML表单上使用的内容类型!

<form enctype="multipart/form-data" accept-charset="utf-8" action="post">
    <input type="file" name="resume">
</form>

因此,在传统的PHP中,要处理来自HTTP的各种内容类型POST请求,您将学会使用$_POSTfilter_input_array(POST),$_FILESphp://input. 没有办法只为HTTP使用一个通用输入源POSTPHP中的请求。
您无法通过$_POST,filter_input_array(POST)php://input,并且在其中都无法获取JSON/XML/YAMLfilter_input_array(POST)$_POST.
PHP手册:php://input

php://input是一个只读流,允许您读取原始数据请求正文…php://input是无法使用的具有

PHP框架的拯救?
像Codeigniter 4和Laravel这样的PHP框架使用facade来提供更干净的界面(IncomingRequestRequest对象)。这就是专业PHP开发人员使用框架而不是原始PHP的原因。
当然,如果您喜欢编程,可以设计自己的facade对象来提供框架的功能。正是因为我花了时间研究这个问题,我才能够写出这个答案。
URL编码?搞什么鬼!!!???
通常,如果您使用HTML表单执行正常、同步(当整个页面重新绘制时)HTTP请求,则用户代理(web浏览器)将为您对表单数据进行URL编码。如果要使用XmlHttpRequest对象,则必须生成URL编码的字符串并发送,如果您希望数据显示在$_POST超全局.
您与JavaScript的联系如何?:-)
从JavaScript数组或对象转换为urlencoded字符串困扰着许多开发人员(即使是像这样的新API)表单数据). 他们更希望能够发送JSON,这将是更高效让客户端代码这样做。
记住(wink,wink),一般的web开发人员不会学习使用XmlHttpRequest直接对象、全局函数、字符串函数、数组函数和正则表达式,如you和I;-)。URL编码对他们来说是一场噩梦
PHP,给了什么?
PHP缺乏直观的XML和JSON处理,这让很多人感到厌烦。你可能认为它现在已经成为PHP的一部分了(叹气)。
如此多的媒体类型(过去的MIME类型)
XML、JSON和YAML都有可以放入HTTP的媒体类型Content-Type标题。

  • 应用程序/xml
  • 应用程序/json
  • 应用程序/yaml(尽管IANA没有列出官方名称)

看看有多少媒体类型(以前,MIME类型)由IANA定义。
看看有多少HTTP标头有。
php://input或者半身像
使用php://inputstream允许您绕过PHP强加给世界的婴儿看护/手持抽象级别伟大的力量带来伟大的责任!
现在,在处理流经的数据值之前php://input,你应该/必须做几件事。

  1. 确定是否正确HTTP方法已指示(GET、POST、,
  2. 确定HTTP内容类型标头已传输。
  3. 确定价值因为内容类型是所需的媒体
  4. 确定发送的数据是否结构合理的XML/JSON/YAML/
  5. 如有必要,转换数据到PHP数据类型:数组或
  6. 如果这些基本检查或转换中的任何一个失败,则引发异常!

那么字符编码呢?
啊,哈!是的,您可能希望发送到应用程序中的数据流是UTF-8编码的,但您如何知道它是否是UTF-8编码的?
两个关键问题。

  1. 你不知道有多少数据通过php://input.
  2. 您无法确定数据流的当前编码。

您是否打算在不知道首先要处理多少流数据的情况下尝试处理流数据?这是个糟糕的主意. 您不能完全依赖HTTPContent-Length标题用于指导流输入的大小,因为它可以被欺骗。
您需要:

  1. 流大小检测算法。
  2. 应用程序定义的流大小限制(Apache/Nginx/PHP限制可能太宽)。

您是否打算在不知道流的当前编码的情况下将流数据转换为UTF-8?怎样iconv流过滤器(iconv流过滤器示例)似乎需要一个开始和结束编码,就像这样。

'convert.iconv.ISO-8859-1/UTF-8'

因此,如果你认真负责,你需要:

  1. 流编码检测算法。
  2. 动态/运行时流过滤器定义算法(因为您无法事先知道开始编码)。

(使现代化:'convert.iconv.UTF-8/UTF-8'将强制所有内容使用UTF-8,但您仍然必须考虑iconv库可能不知道如何翻译的字符。换句话说,您必须了解如何定义无法翻译字符时要采取的操作:1)插入虚拟字符,2)失败/抛出和异常)。
您不能完全依赖HTTPContent-Encoding标题,因为这可能表示压缩,如下所示。这不是您想要对iconv做出的决定。

Content-Encoding: gzip

因此,一般步骤可能是。。。
第一部分:HTTP请求相关

  1. 确定是否正确HTTP方法已指示(GET、POST、,
  2. 确定HTTP内容类型标头已传输。
  3. 确定价值因为内容类型是所需的媒体

第二部分:流数据相关

  1. 确定输入流的大小(可选,但推荐)。
  2. 确定输入流的编码。
  3. 如有必要,将输入流转换为所需的字符
  4. 如有必要,请反转任何应用程序级压缩或加密,然后重复步骤4、5和6。

第三部分:相关数据类型

  1. 确定发送的数据是否结构合理的XML/JSON/YMAL/

(请记住,数据仍然可以是URL编码的字符串,然后必须对其进行解析和URL解码)。

  1. 如有必要,转换数据到PHP数据类型:数组或

第四部分:数据值相关

  1. 过滤输入数据。
  2. 验证输入数据。

现在你明白了吗?
这个$_POST超全局,以及php。ini输入限制设置对于外行来说更简单。然而,在使用流时,处理字符编码更直观、更高效,因为不需要通过超全局(通常是数组)来检查输入值是否正确编码。

Lox 回复 19小时 前

哦,哇!这个答案应该有更高的评分。非常感谢您将泛光灯引入黑暗。

Anthony Rutledge 回复 19小时 前

归根结底,PHP可以很好地更新基本默认值。然而,将HTTP请求方法与同名的数据结构($\u GET,$\u POST)耦合在一起在逻辑上是错误的。重要的是(1)所需的HTTP请求方法,以及(2)该请求是否有请求数据(内容类型)。因此,与Perl一样,您开始意识到自己可能会成为语言创建者/维护者意见的牺牲品

0
Rob Agar 回答 19小时 前

php://input可以为您提供数据的原始字节。如果发布的数据是JSON编码的结构,这将非常有用,这通常适用于AJAX POST请求。
下面是一个函数:

/**
   * Returns the JSON encoded POST data, if any, as an object.
   * 
   * @return Object|null
   */
  private function retrieveJsonPostData()
  {
    // get the raw POST data
    $rawData = file_get_contents("php://input");

    // this returns null if not valid json
    return json_decode($rawData);
  }

这个$_POST当处理由传统帖子提交的表单中的键值数据时,数组更有用。这仅在发布的数据采用公认格式时有效,通常情况下application/x-www-form-urlencoded(参见http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4详细信息)。

Vahid Amiri 回复 19小时 前

值得注意的是,如果你通过了true作为第二个参数json_decode,它将返回一个关联数组。

Anthony Rutledge 回复 19小时 前

小心直接从php://input. 了解流过滤器,确保获得UTF-8编码数据。

Anthony Rutledge 回复 19小时 前

如果没有使用输入滤波器来确保您正在处理UTF-8,请不要这样做。'convert.iconv.UTF-8/UTF-8'

0
Nameless 回答 19小时 前

如果post数据格式不正确,$\u post将不包含任何内容。然而php://input将具有格式错误的字符串。
例如,有些ajax应用程序没有形成正确的post键值序列来上载文件,只是将所有文件作为post数据转储,没有变量名或任何内容。

Brad Rhoads 回复 19小时 前

$\u请求也将为空。

0
Danilo Rodas 回答 19小时 前
if (strtoupper($_SERVER['REQUEST_METHOD']) != 'POST') {
  throw new Exception('Only POST requests are allowed');
}

// Make sure Content-Type is application/json 
$content_type = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '';
if (stripos($content_type, 'application/json') === false) {
  throw new Exception('Content-Type must be application/json');
}

// Read the input stream
$body = file_get_contents("php://input");
 
// Decode the JSON object
$object = json_decode($body, true);