PHP, cURL,和HTTP POST的例子?

有人能告诉我如何用HTTP POST做一个PHP cURL吗?

我想这样发送数据:

username=user1, password=passuser1, gender=1

为# EYZ0

我希望cURL返回类似result=OK的响应。有什么例子吗?

1516055 次浏览
<?php
//
// A very simple PHP example that sends a HTTP POST to a remote site
//


$ch = curl_init();


curl_setopt($ch, CURLOPT_URL,"http://www.example.com/tester.phtml");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,
"postvar1=value1&postvar2=value2&postvar3=value3");


// In real life you should use something like:
// curl_setopt($ch, CURLOPT_POSTFIELDS,
//          http_build_query(array('postvar1' => 'value1')));


// Receive server response ...
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);


$server_output = curl_exec($ch);


curl_close ($ch);


// Further processing ...
if ($server_output == "OK") { ... } else { ... }
?>

如果表单使用重定向、身份验证、cookie、SSL (https)或其他任何东西,而不是期望POST变量的完全开放脚本,那么您将很快开始咬牙切齿。看一下史努比,它完全满足了您的想法,同时消除了设置大量开销的需要。

如果您要将信息传递到您自己的网站,一个更简单的答案是使用SESSION变量。开始php页面:

session_start();

如果在某些情况下,您希望在PHP中生成信息并将其传递到会话中的下一页,则不要使用POST变量,而是将其分配给session变量。例子:

$_SESSION['message']='www.'.$_GET['school'].'.edu was not found.  Please try again.'

然后在下一页中只需引用这个SESSION变量。注意:在你使用它之后,一定要销毁它,这样它就不会在使用后继续存在:

if (isset($_SESSION['message'])) {echo $_SESSION['message']; unset($_SESSION['message']);}
下面是PHP + curl的一些样板代码 # EYZ0 < / p >

包含在这些库中将简化开发

<?php
# Initialization
include("LIB_http.php");
include("LIB_parse.php");
$product_array=array();
$product_count=0;


# Download the target (store) web page
$target = "http://www.tellmewhenitchanges.com/buyair";
$web_page = http_get($target, "");
...
?>

一个使用php curl_exec来做一个HTTP post的实例:

把它放在一个名为foobar.php的文件中:

<?php
$ch = curl_init();
$skipper = "luxury assault recreational vehicle";
$fields = array( 'penguins'=>$skipper, 'bestpony'=>'rainbowdash');
$postvars = '';
foreach($fields as $key=>$value) {
$postvars .= $key . "=" . $value . "&";
}
$url = "http://www.google.com";
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST, 1);                //0 for a get request
curl_setopt($ch,CURLOPT_POSTFIELDS,$postvars);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT ,3);
curl_setopt($ch,CURLOPT_TIMEOUT, 20);
$response = curl_exec($ch);
print "curl response is:" . $response;
curl_close ($ch);
?>

然后使用命令php foobar.php运行它,它会将这种输出转储到屏幕上:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Title</title>


<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<body>
A mountain of content...
</body>
</html>

因此,您执行了一个PHP POST到www.google.com,并向其发送了一些数据。

如果服务器被编程为读入post变量,它可以基于此决定做一些不同的事情。

可以通过以下方式轻松到达:

<?php


$post = [
'username' => 'user1',
'password' => 'passuser1',
'gender'   => 1,
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.domain.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
$response = curl_exec($ch);
var_export($response);

程序上的

// set post fields
$post = [
'username' => 'user1',
'password' => 'passuser1',
'gender'   => 1,
];


$ch = curl_init('http://www.example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);


// execute!
$response = curl_exec($ch);


// close the connection, release resources used
curl_close($ch);


// do anything you want with your response
var_dump($response);

面向对象的

<?php


// mutatis mutandis
namespace MyApp\Http;


class CurlPost
{
private $url;
private $options;
           

/**
* @param string $url     Request URL
* @param array  $options cURL options
*/
public function __construct($url, array $options = [])
{
$this->url = $url;
$this->options = $options;
}


/**
* Get the response
* @return string
* @throws \RuntimeException On cURL error
*/
public function __invoke(array $post)
{
$ch = \curl_init($this->url);
        

foreach ($this->options as $key => $val) {
\curl_setopt($ch, $key, $val);
}


\curl_setopt($ch, \CURLOPT_RETURNTRANSFER, true);
\curl_setopt($ch, \CURLOPT_POSTFIELDS, $post);


$response = \curl_exec($ch);
$error    = \curl_error($ch);
$errno    = \curl_errno($ch);
        

if (\is_resource($ch)) {
\curl_close($ch);
}


if (0 !== $errno) {
throw new \RuntimeException($error, $errno);
}
        

return $response;
}
}

使用

// create curl object
$curl = new \MyApp\Http\CurlPost('http://www.example.com');


try {
// execute the request
echo $curl([
'username' => 'user1',
'password' => 'passuser1',
'gender'   => 1,
]);
} catch (\RuntimeException $ex) {
// catch errors
die(sprintf('Http error %s with code %d', $ex->getMessage(), $ex->getCode()));
}

旁注:最好创建一些名为AdapterInterface的接口,例如使用getResponse()方法,并让上面的类实现它。然后,您总是可以将这个实现与您喜欢的另一个适配器交换,而不会对应用程序产生任何副作用。

使用HTTPS /加密流量

在Windows操作系统下,PHP中的cURL通常会有问题。在尝试连接到受https保护的端点时,您将得到一个错误,告诉您certificate verify failed. #。

大多数人在这里做的是告诉cURL库简单地忽略证书错误并继续(curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);)。因为这将使你的代码正常工作,你引入了巨大的安全漏洞,并使恶意用户能够对你的应用程序进行各种攻击,如夹在中间的人攻击或类似的攻击。

永远,永远不要那样做。相反,你只需要修改你的php.ini,并告诉PHP你的CA Certificate文件在哪里,让它正确地验证证书:

; modify the absolute path to the cacert.pem file
curl.cainfo=c:\php\cacert.pem

最新的cacert.pem可以从互联网或从您最喜欢的浏览器提取下载。当更改任何php.ini相关设置时,记得重新启动您的web服务器。

curlPost('google.com', [
'username' => 'admin',
'password' => '12345',
]);




function curlPost($url, $data) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error !== '') {
throw new \Exception($error);
}


return $response;
}

Curl Post +错误处理+设置头[感谢@mantas-d]:

function curlPost($url, $data=NULL, $headers = NULL) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);


if(!empty($data)){
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}


if (!empty($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}


$response = curl_exec($ch);


if (curl_error($ch)) {
trigger_error('Curl Error:' . curl_error($ch));
}


curl_close($ch);
return $response;
}




curlPost('google.com', [
'username' => 'admin',
'password' => '12345',
]);

如果你试图用cookies登录网站。

这段代码:

if ($server_output == "OK") { ... } else { ... }

如果您尝试登录,它可能无法工作,因为许多网站返回状态200,但发布不成功。

检查登录帖子是否成功的简单方法是检查它是否再次设置cookie。如果在输出中有一个Set-Cookies字符串,这意味着帖子没有成功,它开始一个新的会话。

同样,帖子可以成功,但是状态可以重定向,而不是200。

为了确保帖子成功,试试下面的方法:

Follow location在post之后,所以它会转到post重定向到的页面:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

然后检查请求中是否存在新的cookie:

if (!preg_match('/^Set-Cookie:\s*([^;]*)/mi', $server_output))


{echo 'post successful'; }


else { echo 'not successful'; }

发送形式数据的例子:

$curlHandler = curl_init();


curl_setopt_array($curlHandler, [
CURLOPT_URL => 'https://postman-echo.com/post',
CURLOPT_RETURNTRANSFER => true,


/**
* Specify POST method
*/
CURLOPT_POST => true,


/**
* Specify array of form fields
*/
CURLOPT_POSTFIELDS => [
'foo' => 'bar',
'baz' => 'biz',
],
]);


$response = curl_exec($curlHandler);


curl_close($curlHandler);


echo($response);

1.一步一步

  • 初始化cURL会话:
$url = "www.domain.com";
$ch = curl_init($url);
  • 如果你的请求有报头,如承载令牌或定义JSON内容,你必须设置HTTPHEADER选项为cURL:
$token = "generated token code";
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json', // for define content type that is json
'bearer: '.$token, // send token in header request
'Content-length: 100' // content length for example 100 characters (can add by strlen($fields))
)
);
  • 如果你想在输出集CURLOPT_HEADERtrue中包含头文件:
curl_setopt($ch, CURLOPT_HEADER, false);
  • RETURNTRANSFER选项设置为true,以字符串形式返回传输,而不是直接输出:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  • 要检查SSL对端证书中是否存在公共名称,可以设置为0(to not check the names)1(not supported in cURL 7.28.1)2(default value and for production mode):
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
  • 对于cURL将字段作为数组发布:
$fields = array(
"username" => "user1",
"password" => "passuser1",
"gender" => 1
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
  • 执行cURL并返回字符串。根据你的资源,这将返回类似result=OK的输出:
$result = curl_exec($ch);
  • 关闭cURL资源,释放系统资源:
curl_close($ch);

2.作为一个类使用

  • 可以扩展的整个call_cURL类:
class class_name_for_call_cURL {
protected function getUrl() {
return "www.domain.com";
}


public function call_cURL() {
$token = "generated token code";


$fields = array(
"username" => "user1",
"password" => "passuser1",
"gender" => 1
);


$url = $this->getUrl();
$output = $this->_execute($fields, $url, $token);
        

// if you want to get json data
// $output = json_decode($output);
            

if ($output == "OK") {
return true;
} else {
return false;
}
}


private function _execute($postData, $url, $token) {
// for sending data as json type
$fields = json_encode($postData);


$ch = curl_init($url);
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json', // if the content type is json
'bearer: '.$token // if you need token in header
)
);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);


$result = curl_exec($ch);
curl_close($ch);


return $result;
}
}
  • 使用类并调用cURL:
$class = new class_name_for_call_cURL();
var_dump($class->call_cURL()); // output is true/false

3.一个函数

  • 在任何需要的地方使用的函数:
function get_cURL() {


$url = "www.domain.com";
$token = "generated token code";


$postData = array(
"username" => "user1",
"password" => "passuser1",
"gender" => 1
);


// for sending data as json type
$fields = json_encode($postData);


$ch = curl_init($url);
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json', // if the content type is json
'bearer: '.$token // if you need token in header
)
);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);


$result = curl_exec($ch);
curl_close($ch);


return $result;
}
  • 这个函数可以通过以下方式使用:
var_dump(get_cURL());

我很惊讶没有人建议file_get_contents:

$url = "http://www.example.com";
$parameters = array('username' => 'user1', 'password' => 'passuser1', 'gender' => '1');
$options = array('http' => array(
'header'  => 'Content-Type: application/x-www-form-urlencoded\r\n',
'method'  => 'POST',
'content' => http_build_query($parameters)
));


$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);

这很简单,很有效;我把它用在两端都能控制代码的环境中。

更好的方法是使用json_decode(并设置代码以返回JSON)

$result = json_decode(file_get_contents($url, false, $context), TRUE);

这种方法在幕后调用curl,但不需要经历那么多困难。

从堆栈溢出的其他地方的原始答案提炼出来的答案: # EYZ0 < / p >

最简单的是以application/json的形式发送数据。这将接受一个数组作为输入,并正确地将其编码为json字符串:

$data = array(
'field1' => 'field1value',
'field2' => 'field2value',
)


$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));


curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type:application/json',
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$resultStr = curl_exec($ch);
return json_decode($resultStr, true);