实际上我想读取搜索查询后的内容。问题在于URL只接受POST
方法,而不接受任何使用GET
方法的操作...
我必须利用domdocument
或file_get_contents()
来读取所有的内容。是否有一种方法可以让我通过PHP
使用POST
方法发送参数,然后读取内容?
$url = 'http://server.com/path';
$data = ['key1' => 'value1', 'key2' => 'value2'];
// use key 'http' even if you send the request to https://...
$options = [
'http' => [
'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);
你可以使用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;
?>
count($fields)
的目的是什么?为什么不将其设置为1? - Nubcake我使用以下函数使用curl发送数据。 $data
是要发布的字段数组(将使用http_build_query()
正确编码)。
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提到可以省略http_build_query()
,因为curl会正确编码传递给CURLOPT_POSTFIELDS
参数的数组,这是正确的,但请注意,在这种情况下,数据将使用multipart/form-data
进行编码,并且可能不希望一些终点使用application/x-www-form-urlencoded
进行编码。在上面的函数中使用http_build_query()
时,数据将使用application/x-www-form-urlencoded
进行编码。
... CURLOPT_RETURNTRANSFER, true
的结果是 $response
包含了内容。 - ToolmakerSteve我建议你使用开源包guzzle,该包经过全面单元测试并采用了最新的编码规范。
安装Guzzle
前往您项目文件夹中的命令行,并输入以下命令(假设您已经安装了包管理器composer)。如果您需要帮助安装Composer,请点击此处。
php composer.phar require guzzlehttp/guzzle
使用 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);
我希望能对Fred Tanrikut基于curl的答案进行一些补充。虽然大部分内容已经在上面的回答中提到了,但我认为将它们汇总在一起展示是个好主意。
以下是我编写的一个类,它基于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;
}
}
http_build_query
函数从请求数组中获取查询字符串。(你也可以使用数组本身,参见:http://php.net/manual/zh/function.curl-setopt.php)$response = HTTPRequester::HTTPGet("http://localhost/service/foobar.php", array("getParam" => "foobar"));
$response = HTTPRequester::HTTPPost("http://localhost/service/foobar.php", array("postParam" => "foobar"));
$response = HTTPRequester::HTTPPut("http://localhost/service/foobar.php", array("putParam" => "foobar"));
$response = HTTPRequester::HTTPDelete("http://localhost/service/foobar.php", array("deleteParam" => "foobar"));
您可以使用这个简单的类制作一些很酷的服务测试。
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}]');
}
}
$response = wp_remote_post( $url, array('body' => $parameters));
if ( is_wp_error( $response ) ) {
// $response->get_error_message()
} else {
// $response['body']
}
根据Web服务器上可用的方式,它使用不同的方法来进行实际的HTTP请求。有关更多详细信息,请参阅HTTP API文档。
如果您不想开发自定义主题或插件来启动WordPress引擎,您可以在WordPress根目录中的一个独立的PHP文件中执行以下操作:
require_once( dirname(__FILE__) . '/wp-load.php' );
// ... your code
它不会显示任何主题或输出任何HTML,只需使用WordPress API进行编程!
如果您想使用 CURL 方法,还有另一种选择。
一旦理解了 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
首先,我们初始化连接,然后使用setopt()设置一些选项。这些选项告诉PHP我们正在进行post请求,并且我们正在提供数据。CURLOPT_RETURNTRANSFER标志告诉curl将输出作为curl_exec的返回值而不是输出它。接下来,我们发出调用并关闭连接——结果在$response中。
$ch
而不是$curl
,对吗? - jcomeau_ictx另一种不需要curl的替代方法是使用本地流函数:
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) {
return json_encode(['error' => 'Failed to get contents...']);
}
$result = stream_get_contents($fp); // no maxlength/offset
fclose($fp);
return $result;
}
$fp
是 false
,则无需使用 fclose()
。因为 fclose()
需要一个资源作为参数。 - Floris这里只使用一个命令,而不需要使用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'
])
]
]));
使用以下方式是在PHP
中发送GET
或POST
请求的更好方法:
<?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;
}
?>
这段代码来自官方文档,位于http://docs.php.net/manual/da/httprequest.send.php
file_get_contents()
的文件名。请参见http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen。 - Pinofile_get_contents()
是PHP核心的一部分。此外,不必要地使用扩展可以增加应用程序受攻击的面。例如,Google搜索“php curl cve”。 - Pocketsand