如何使用PHP发送POST请求?

Fre*_*kut 622 php post http request

实际上我想读完搜索查询后的内容.问题是URL只接受POST方法,并且不对GET方法采取任何操作......

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

dba*_*bau 1203

PHP5的CURL-less方法:

$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);
Run Code Online (Sandbox Code Playgroud)

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

  • 值得注意的是,如果您决定使用数组作为标题,请不要使用'\ r \n'结束键或值.stream_context_create()只会将文本带到第一个'\ r \n' (59认同)
  • @jvannistelrooy PHP的CURL是一个扩展,可能并不存在于所有环境中,而`file_get_contents()`是PHP核心的一部分.此外,不必要地使用扩展可能会扩大应用程序的攻击面.例如Google [php curl cve](https://www.google.com/search?q=php+curl+cve) (34认同)
  • 是否有特定原因不使用CURL? (13认同)
  • 只有在启用了fopen包装器的情况下,URL才能用作`file_get_contents()`的文件名.见http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen (10认同)
  • 需要注意的一件事:如果您以 JSON 形式发送 POST 请求正文:对于标头,请使用 `Content-Type: application/json`;对于内容,使用 `json_encode` 而不是 `http_build_query`:`json_encode($data)`。 (5认同)
  • @I love`file_get_contents()` (3认同)
  • 我尝试了这个,但我取回了文件的全部内容:( (2认同)
  • 对于此代码,我的本地主机发送 GET 方法。请告诉如何启用POST (2认同)
  • bool(false)我得到了?? (2认同)
  • 我也得到bool(false),不起作用,我不认为 (2认同)

Fre*_*kut 126

你可以使用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;
?>
Run Code Online (Sandbox Code Playgroud)

  • 您没有从以下位置复制此代码示例的站点:http://davidwalsh.name/curl-post (75认同)
  • file_get_contents解决方案不适用于使用allow_url_fopen Off的PHP配置(就像在共享主机中一样).这个版本使用curl库,我认为最"普遍",所以我给你投票 (8认同)
  • 这个对我有用,因为我发送到没有内容的页面的页面因此file_get_contents版本不起作用. (3认同)
  • 虽然它不是很重要,但实际上不需要将CURLOPT_POSTFIELDS参数数据转换为字符串("urlified").引用:"此参数既可以作为urlencoded字符串传递,如'para1 = val1&para2 = val2&...',也可以作为数组,字段名称为键,字段数据为值.如果value是数组,则为Content-Type标题将设置为multipart/form-data." 链接:http://php.net/manual/en/function.curl-setopt.php. (3认同)
  • 另外,对于以不同方式编写它没有任何冒犯,但我不知道为什么CURLOPT_POST参数被指定为数字,因为它说它在手册页上将其设置为布尔值.Quote:"CURLOPT_POST:TRUE进行常规HTTP POST." 链接:http://php.net/manual/en/function.curl-setopt.php. (2认同)

Dim*_* L. 61

我使用以下函数使用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;
}
Run Code Online (Sandbox Code Playgroud)

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

我将此函数与API一起使用,期望使用application/x-www-form-urlencoded编码数据.这就是我使用http_build_query()的原因.


And*_*eas 40

我建议你使用开源包狂饮即完全单元测试,并采用了最新的编码实践.

安装Guzzle

转到项目文件夹中的命令行,然后键入以下命令(假设您已经安装了包管理器编写器).如果您需要有关如何安装Composer的帮助,请查看此处.

php composer.phar require guzzlehttp/guzzle
Run Code Online (Sandbox Code Playgroud)

使用Guzzle发送POST请求

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);
Run Code Online (Sandbox Code Playgroud)

  • @artfulrobot:本机PHP解决方案存在很多问题(例如连接https,证书验证等等),这就是几乎每个PHP开发人员都使用cURL的原因.为什么不在这种情况下使用cURL?这很简单:Guzzle有一个直接,简单,轻量级的界面,可以将所有那些"低级cURL处理问题"抽象出来.几乎所有开发现代PHP的人都使用Composer,因此使用Guzzle非常简单. (7认同)
  • 了解它与已发布的本机PHP解决方案相比有什么优势,以及cURL也是有用的. (6认同)
  • 谢谢,我知道guzzle很受欢迎,但是当作曲家引起悲伤时会有用例(例如为可能已经使用(不同版本)guzzle或其他依赖项的更大的软件项目开发插件),所以知道这些信息是很好的关于哪种解决方案最强大的决定 (2认同)
  • @Andreas,虽然你是对的,但这是一个很好的例子,越来越多的抽象导致对低级技术的理解越来越少,从而导致越来越多的开发人员不知道他们在那里做什么,甚至无法调试一个简单的请求。 (2认同)
  • @clockw0rk不幸的是,你是对的。但抽象(在某种程度上)仍然是有用的,可以节省大量时间和错误/潜在的错误。显然,每个使用 Guzzle 的人都应该能够调试请求,并且对网络和 HTTP 的工作原理有基本的了解。 (2认同)

Jos*_*vic 25

如果你这样做,还有另一种CURL方法.

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

$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
Run Code Online (Sandbox Code Playgroud)

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


小智 20

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

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

if ( is_wp_error( $response ) ) {
    // $response->get_error_message()
} else {
    // $response['body']
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

// ... your code
Run Code Online (Sandbox Code Playgroud)

它不会显示任何主题或输出任何HTML,只是破解Wordpress API!


mwa*_*zer 19

我想补充一些关于Fred Tanrikut基于卷曲的答案的想法.我知道他们中的大多数已经写在上面的答案中,但我认为最好显示一个包含所有这些答案的答案.

这是我写的基于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;
    }
}
Run Code Online (Sandbox Code Playgroud)

改进

  • 使用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会产生更易读的代码,但这只是我的意见)
  • 能够进行HTTP-PUT/DELETE调用(对RESTful服务测试很有用)

用法示例

得到

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

POST

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

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

删除

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

测试

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

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}]');
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 好吧,现在我看到了问题,..示例中是错误的!您必须调用 HTTPRequester::HTTPPost() 而不是 HTTPRequester::HTTPost() (2认同)

CPH*_*hon 14

上面无卷曲方法的另一种替代方法是使用本机函数:

  • stream_context_create():

    使用选项预设中提供的任何选项创建并返回流上下文.

  • stream_get_contents():

    file_get_contents()除了stream_get_contents() 对已经打​​开的流资源进行操作并以字符串形式返回剩余内容之外,与之相同,最多为maxlength字节,并从指定的偏移量开始.

这些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) {
    fclose($fp);
    return json_encode(['error' => 'Failed to get contents...']);
  }
  $result = stream_get_contents($fp); // no maxlength/offset
  fclose($fp);
  return $result;
}
Run Code Online (Sandbox Code Playgroud)


Lig*_*iga 13

这里只使用一个没有 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'
        ])
    ]
]));
Run Code Online (Sandbox Code Playgroud)


Bas*_*asj 9

根据主要答案,我使用的是:

function do_post($url, $params) {
    $options = array(
        'http' => array(
            'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
            'method'  => 'POST',
            'content' => $params
        )
    );
    $result = file_get_contents($url, false, stream_context_create($options));
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

do_post('https://www.google-analytics.com/collect', 'v=1&t=pageview&tid=UA-xxxxxxx-xx&cid=abcdef...');
Run Code Online (Sandbox Code Playgroud)


Cod*_*ode 5

还有一个你可以使用

<?php
$fields = array(
    'name' => 'mike',
    'pass' => 'se_ret'
);
$files = array(
    array(
        'name' => 'uimg',
        'type' => 'image/jpeg',
        'file' => './profile.jpg',
    )
);

$response = http_post_fields("http://www.example.com/", $fields, $files);
?>
Run Code Online (Sandbox Code Playgroud)

点击此处了解详情

  • 这依赖于PECL扩展,大多数扩展都不会安装。由于手册页已被删除,因此甚至不确定它是否仍然可用。 (2认同)
  • 点击此处查看详情链接无效 (2认同)

Ari*_*yak 5

我正在寻找类似的问题,并找到了更好的方法来做到这一点.所以这就是它.

您只需将以下行放在重定向页面上(例如page1.php)即可.

header("Location: URL", TRUE, 307); // Replace URL with to be redirected URL, e.g. final.php
Run Code Online (Sandbox Code Playgroud)

我需要这个来重定向REST API调用的POST请求.此解决方案能够使用发布数据以及自定义标头值重定向.

这是参考链接.

  • 这回答了如何*重定向页面请求*而不是*如何使用 PHP 发送 POST 请求?* 当然这会转发任何 POST 参数,但这根本不是同一件事 (2认同)

Imr*_*oor 5

更好的发送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;
    }
?>
Run Code Online (Sandbox Code Playgroud)

该代码来自官方文档,网址为http://docs.php.net/manual/da/httprequest.send.php

  • 这不是原生 PHP。这需要 pecl http。 (3认同)

cwe*_*ske 2

尝试 PEAR 的HTTP_Request2包来轻松发送 POST 请求。或者,您可以使用 PHP 的curl 函数或使用 PHP流上下文

HTTP_Request2 还可以模拟服务器,因此您可以轻松地对代码进行单元测试

  • 如果可能的话,我希望您能详细说明一下。 (10认同)