如何使用 PHP 发送 POST 请求?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5647461/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 22:05:39  来源:igfitidea点击:

How do I send a POST request with PHP?

phphttppostrequest

提问by Fred Tanrikut

Actually I want to read the contents that come after the search query, when it is done. The problem is that the URL only accepts POSTmethods, and it does not take any action with GETmethod...

实际上,我想阅读搜索查询之后的内容,完成后。问题是URL只接受POST方法,对GET方法不做任何动作...

I have to read all contents with the help of domdocumentor file_get_contents(). Is there any method that will let me send parameters with POSTmethod and then read the contents via PHP?

我必须在domdocument或的帮助下阅读所有内容file_get_contents()。有没有什么方法可以让我用POST方法发送参数然后通过读取内容PHP

回答by dbau

CURL-less method with PHP5:

使用 PHP5 的无 CURL 方法:

$url = 'http://server.com/path';
$data = array('key1' => 'value1', 'key2' => 'value2');

// use key 'http' even if you send the request to https://...
$options = array(
    'http' => array(
        'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
        'method'  => 'POST',
        'content' => http_build_query($data)
    )
);
$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */ }

var_dump($result);

See the PHP manual for more information on the method and how to add headers, for example:

有关该方法以及如何添加标题的更多信息,请参阅 PHP 手册,例如:

回答by Fred Tanrikut

You could use cURL:

您可以使用cURL

<?php
//The url you wish to send the POST request to
$url = $file_name;

//The data you want to send via POST
$fields = [
    '__VIEWSTATE '      => $state,
    '__EVENTVALIDATION' => $valid,
    'btnSubmit'         => 'Submit'
];

//url-ify the data for the POST
$fields_string = http_build_query($fields);

//open connection
$ch = curl_init();

//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, true);
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);

//So that curl_exec returns the contents of the cURL; rather than echoing it
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true); 

//execute post
$result = curl_exec($ch);
echo $result;
?>

回答by Dima L.

I use the following function to post data using curl. $data is an array of fields to post (will be correctly encoded using http_build_query). The data is encoded using application/x-www-form-urlencoded.

我使用以下函数使用 curl 发布数据。$data 是要发布的字段数组(将使用 http_build_query 正确编码)。数据使用 application/x-www-form-urlencoded 进行编码。

function httpPost($url, $data)
{
    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($curl);
    curl_close($curl);
    return $response;
}

@Edward mentions that http_build_query may be omitted since curl will correctly encode array passed to CURLOPT_POSTFIELDS parameter, but be advised that in this case the data will be encoded using multipart/form-data.

@Edward 提到 http_build_query 可能会被省略,因为 curl 会正确编码传递给 CURLOPT_POSTFIELDS 参数的数组,但请注意,在这种情况下,数据将使用 multipart/form-data 进行编码。

I use this function with APIs that expect data to be encoded using application/x-www-form-urlencoded. That's why I use http_build_query().

我将此函数与希望使用 application/x-www-form-urlencoded 对数据进行编码的 API 一起使用。这就是我使用 http_build_query() 的原因。

回答by Andreas

I recommend you to use the open-source package guzzlethat is fully unit tested and uses the latest coding practices.

我建议您使用经过全面单元测试并使用最新编码实践的开源软件包guzzle

Installing Guzzle

安装 Guzzle

Go to the command line in your project folder and type in the following command (assuming you already have the package manager composerinstalled). If you need help how to install Composer, you should have a look here.

转到项目文件夹中的命令行并输入以下命令(假设您已经安装了包管理器composer)。如果您需要有关如何安装 Composer 的帮助,您应该查看这里

php composer.phar require guzzlehttp/guzzle

Using Guzzle to send a POST request

使用 Guzzle 发送 POST 请求

The usage of Guzzle is very straight forward as it uses a light-weight object-oriented API:

Guzzle 的使用非常简单,因为它使用了一个轻量级的面向对象 API:

// Initialize Guzzle client
$client = new GuzzleHttp\Client();

// Create a POST request
$response = $client->request(
    'POST',
    'http://example.org/',
    [
        'form_params' => [
            'key1' => 'value1',
            'key2' => 'value2'
        ]
    ]
);

// Parse the response object, e.g. read the headers, body, etc.
$headers = $response->getHeaders();
$body = $response->getBody();

// Output headers and body for debugging purposes
var_dump($headers, $body);

回答by Josip Ivic

There's another CURL method if you are going that way.

如果您要这样做,还有另一种 CURL 方法。

This is pretty straightforward once you get your head around the way the PHP curl extension works, combining various flags with setopt() calls. In this example I've got a variable $xml which holds the XML I have prepared to send - I'm going to post the contents of that to example's test method.

一旦您了解 PHP curl 扩展的工作方式,将各种标志与 setopt() 调用结合起来,这将非常简单。在这个例子中,我有一个变量 $xml ,它保存我准备发送的 XML - 我将把它的内容发布到示例的测试方法中。

$url = 'http://api.example.com/services/xmlrpc/';
$ch = curl_init($url);

curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
//process $response

First we initialised the connection, then we set some options using setopt(). These tell PHP that we are making a post request, and that we are sending some data with it, supplying the data. The CURLOPT_RETURNTRANSFER flag tells curl to give us the output as the return value of curl_exec rather than outputting it. Then we make the call and close the connection - the result is in $response.

首先我们初始化连接,然后我们使用 setopt() 设置一些选项。这些告诉 PHP 我们正在发出一个 post 请求,并且我们正在发送一些数据,提供数据。CURLOPT_RETURNTRANSFER 标志告诉 curl 将输出作为 curl_exec 的返回值提供给我们,而不是输出它。然后我们进行调用并关闭连接 - 结果在 $response 中。

回答by Josip Ivic

If you by any chance are using Wordpress to develop your app (it's actually a convenient way to get authorization, info pages etc even for very simple stuff), you can use the following snippet:

如果您有机会使用 Wordpress 来开发您的应用程序(它实际上是一种获得授权、信息页面等的便捷方式,即使是非常简单的东西),您可以使用以下代码段:

$response = wp_remote_post( $url, array('body' => $parameters));

if ( is_wp_error( $response ) ) {
    // $response->get_error_message()
} else {
    // $response['body']
}

It uses different ways of making the actual HTTP request, depending on what is available on the web server. For more details, see the HTTP API documentation.

它使用不同的方式发出实际的 HTTP 请求,具体取决于 Web 服务器上可用的内容。有关更多详细信息,请参阅HTTP API 文档

If you don't want to develop a custom theme or plugin to start the Wordpress engine, you can just do the following in an isolated PHP file in the wordpress root:

如果您不想开发自定义主题或插件来启动 Wordpress 引擎,您只需在 wordpress 根目录下的独立 PHP 文件中执行以下操作:

require_once( dirname(__FILE__) . '/wp-load.php' );

// ... your code

It won't show any theme or output any HTML, just hack away with the Wordpress APIs!

它不会显示任何主题或输出任何 HTML,只需使用 Wordpress API 即可!

回答by mwatzer

I'd like to add some thoughts about the curl-based answer of Fred Tanrikut. I know most of them are already written in the answers above, but I think it is a good idea to show an answer that includes all of them together.

我想补充一些关于 Fred Tanrikut 基于 curl 的答案的想法。我知道他们中的大多数已经写在上面的答案中,但我认为展示一个包含所有这些的答案是个好主意。

Here is the class I wrote to make HTTP-GET/POST/PUT/DELETE requests based on curl, concerning just about the response body:

这是我编写的基于 curl 发出 HTTP-GET/POST/PUT/DELETE 请求的类,仅涉及响应主体:

class HTTPRequester {
    /**
     * @description Make HTTP-GET call
     * @param       $url
     * @param       array $params
     * @return      HTTP-Response body or an empty string if the request fails or is empty
     */
    public static function HTTPGet($url, array $params) {
        $query = http_build_query($params); 
        $ch    = curl_init($url.'?'.$query);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, false);
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
    /**
     * @description Make HTTP-POST call
     * @param       $url
     * @param       array $params
     * @return      HTTP-Response body or an empty string if the request fails or is empty
     */
    public static function HTTPPost($url, array $params) {
        $query = http_build_query($params);
        $ch    = curl_init();
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
    /**
     * @description Make HTTP-PUT call
     * @param       $url
     * @param       array $params
     * @return      HTTP-Response body or an empty string if the request fails or is empty
     */
    public static function HTTPPut($url, array $params) {
        $query = \http_build_query($params);
        $ch    = \curl_init();
        \curl_setopt($ch, \CURLOPT_RETURNTRANSFER, true);
        \curl_setopt($ch, \CURLOPT_HEADER, false);
        \curl_setopt($ch, \CURLOPT_URL, $url);
        \curl_setopt($ch, \CURLOPT_CUSTOMREQUEST, 'PUT');
        \curl_setopt($ch, \CURLOPT_POSTFIELDS, $query);
        $response = \curl_exec($ch);
        \curl_close($ch);
        return $response;
    }
    /**
     * @category Make HTTP-DELETE call
     * @param    $url
     * @param    array $params
     * @return   HTTP-Response body or an empty string if the request fails or is empty
     */
    public static function HTTPDelete($url, array $params) {
        $query = \http_build_query($params);
        $ch    = \curl_init();
        \curl_setopt($ch, \CURLOPT_RETURNTRANSFER, true);
        \curl_setopt($ch, \CURLOPT_HEADER, false);
        \curl_setopt($ch, \CURLOPT_URL, $url);
        \curl_setopt($ch, \CURLOPT_CUSTOMREQUEST, 'DELETE');
        \curl_setopt($ch, \CURLOPT_POSTFIELDS, $query);
        $response = \curl_exec($ch);
        \curl_close($ch);
        return $response;
    }
}

Improvements

改进

  • Using http_build_query to get the query-string out of an request-array.(you could also use the array itself, therefore see: http://php.net/manual/en/function.curl-setopt.php)
  • Returning the response instead of echoing it. Btw you can avoid the returning by removing the line curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);. After that the return value is a boolean(true = request was successful otherwise an error occured) and the response is echoed. See: http://php.net/en/manual/function.curl-exec.php
  • Clean session closing and deletion of the curl-handler by using curl_close. See: http://php.net/manual/en/function.curl-close.php
  • Using boolean values for the curl_setoptfunction instead of using any number.(I know that any number not equal zero is also considered as true, but the usage of true generates a more readable code, but that's just my opinion)
  • Ability to make HTTP-PUT/DELETE calls(useful for RESTful service testing)
  • 使用 http_build_query 从请求数组中获取查询字符串。(您也可以使用数组本身,因此请参阅:http: //php.net/manual/en/function.curl-setopt.php
  • 返回响应而不是回应它。顺便说一句,您可以通过删除curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);行来避免返回. 之后返回值是一个布尔值(true = 请求成功,否则发生错误)并且响应被回显。见:http: //php.net/en/manual/function.curl-exec.php
  • 使用curl_close清理会话关闭和 curl 处理程序的删除。见:http: //php.net/manual/en/function.curl-close.php
  • curl_setopt函数使用布尔值而不是使用任何数字。(我知道任何不等于零的数字也被认为是 true,但使用 true 会生成更易读的代码,但这只是我的意见)
  • 能够进行 HTTP-PUT/DELETE 调用(用于 RESTful 服务测试)

Example of usage

使用示例

GET

得到

$response = HTTPRequester::HTTPGet("http://localhost/service/foobar.php", array("getParam" => "foobar"));

POST

邮政

$response = HTTPRequester::HTTPPost("http://localhost/service/foobar.php", array("postParam" => "foobar"));

PUT

$response = HTTPRequester::HTTPPut("http://localhost/service/foobar.php", array("putParam" => "foobar"));

DELETE

删除

$response = HTTPRequester::HTTPDelete("http://localhost/service/foobar.php", array("deleteParam" => "foobar"));

Testing

测试

You can also make some cool service tests by using this simple class.

您还可以使用这个简单的类进行一些很酷的服务测试。

class HTTPRequesterCase extends TestCase {
    /**
     * @description test static method HTTPGet
     */
    public function testHTTPGet() {
        $requestArr = array("getLicenses" => 1);
        $url        = "http://localhost/project/req/licenseService.php";
        $this->assertEquals(HTTPRequester::HTTPGet($url, $requestArr), '[{"error":false,"val":["NONE","AGPL","GPLv3"]}]');
    }
    /**
     * @description test static method HTTPPost
     */
    public function testHTTPPost() {
        $requestArr = array("addPerson" => array("foo", "bar"));
        $url        = "http://localhost/project/req/personService.php";
        $this->assertEquals(HTTPRequester::HTTPPost($url, $requestArr), '[{"error":false}]');
    }
    /**
     * @description test static method HTTPPut
     */
    public function testHTTPPut() {
        $requestArr = array("updatePerson" => array("foo", "bar"));
        $url        = "http://localhost/project/req/personService.php";
        $this->assertEquals(HTTPRequester::HTTPPut($url, $requestArr), '[{"error":false}]');
    }
    /**
     * @description test static method HTTPDelete
     */
    public function testHTTPDelete() {
        $requestArr = array("deletePerson" => array("foo", "bar"));
        $url        = "http://localhost/project/req/personService.php";
        $this->assertEquals(HTTPRequester::HTTPDelete($url, $requestArr), '[{"error":false}]');
    }
}

回答by CPHPython

Another alternative of the curl-lessmethod aboveis to use the native streamfunctions:

上面curl-less方法的另一种替代方法是使用本机函数:

  • stream_context_create():

    Creates and returns a stream context with any options supplied in optionspreset.

  • stream_get_contents():

    Identical to file_get_contents(), except that stream_get_contents()operates on an already open streamresource and returns the remaining contents in a string, up to maxlengthbytes and starting at the specified offset.

A POST function with these can simply be like this:

带有这些的 POST 函数可以是这样的:

<?php

function post_request($url, array $params) {
  $query_content = http_build_query($params);
  $fp = fopen($url, 'r', FALSE, // do not use_include_path
    stream_context_create([
    'http' => [
      'header'  => [ // header array does not need '\r\n'
        'Content-type: application/x-www-form-urlencoded',
        'Content-Length: ' . strlen($query_content)
      ],
      'method'  => 'POST',
      'content' => $query_content
    ]
  ]));
  if ($fp === FALSE) {
    return json_encode(['error' => 'Failed to get contents...']);
  }
  $result = stream_get_contents($fp); // no maxlength/offset
  fclose($fp);
  return $result;
}

回答by Imran Zahoor

The better way of sending GETor POSTrequests with PHPis as below:

更好的发送GETPOST请求方式PHP如下:

<?php
    $r = new HttpRequest('http://example.com/form.php', HttpRequest::METH_POST);
    $r->setOptions(array('cookies' => array('lang' => 'de')));
    $r->addPostFields(array('user' => 'mike', 'pass' => 's3c|r3t'));

    try {
        echo $r->send()->getBody();
    } catch (HttpException $ex) {
        echo $ex;
    }
?>

The code is taken from official documentation here http://docs.php.net/manual/da/httprequest.send.php

代码取自这里的官方文档http://docs.php.net/manual/da/httprequest.send.php

回答by Liga

Here is using just one command without cURL. Super simple.

这里只使用一个没有 cURL 的命令。超级简单。

echo file_get_contents('https://www.server.com', false, stream_context_create([
    'http' => [
        'method' => 'POST',
        'header'  => "Content-type: application/x-www-form-urlencoded",
        'content' => http_build_query([
            'key1' => 'Hello world!', 'key2' => 'second value'
        ])
    ]
]));