简体   繁体   English

PHP、cURL 和 HTTP POST 示例?

[英]PHP, cURL, and HTTP POST example?

Can anyone show me how to do a PHP cURL with an HTTP POST?谁能告诉我如何用 HTTP POST 做一个 PHP cURL?

I want to send data like this:我想发送这样的数据:

username=user1, password=passuser1, gender=1

To www.example.comwww.example.com

I expect the cURL to return a response like result=OK .我希望 cURL 返回类似result=OK的响应。 Are there any examples?有没有例子?

<?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 { ... }
?>

Procedural程序

// 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);

Object oriented面向对象

<?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;
    }
}

Usage用法

// 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()));
}

Side note here: it would be best to create some kind of interface called AdapterInterface for example with getResponse() method and let the class above implement it.这里的旁注:最好创建某种名为AdapterInterface的接口,例如使用getResponse()方法并让上面的类实现它。 Then you can always swap this implementation with another adapter of your like, without any side effects to your application.然后,您始终可以将此实现与您喜欢的另一个适配器交换,而不会对您的应用程序产生任何副作用。

Using HTTPS / encrypting traffic使用 HTTPS / 加密流量

Usually there's a problem with cURL in PHP under the Windows operating system.通常在 Windows 操作系统下 PHP 的 cURL 会出现问题。 While trying to connect to a https protected endpoint, you will get an error telling you that certificate verify failed .在尝试连接到受 https 保护的端点时,您将收到一条错误消息,告诉您certificate verify failed

What most people do here is to tell the cURL library to simply ignore certificate errors and continue ( curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); ).大多数人在这里所做的是告诉 cURL 库简单地忽略证书错误并继续( curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); )。 As this will make your code work, you introduce huge security hole and enable malicious users to perform various attacks on your app like Man In The Middle attack or such.由于这将使您的代码正常工作,因此您会引入巨大的安全漏洞并使恶意用户能够对您的应用程序执行各种攻击,例如中间人攻击等。

Never, ever do that.永远,永远不要那样做。 Instead, you simply need to modify your php.ini and tell PHP where your CA Certificate file is to let it verify certificates correctly:相反,您只需要修改您的php.ini并告诉 PHP 您的CA Certificate文件在哪里,让它正确验证证书:

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

The latest cacert.pem can be downloaded from the Internet or extracted from your favorite browser .最新的cacert.pem可以从 Internet 下载或从您喜欢的浏览器中提取 When changing any php.ini related settings remember to restart your webserver.更改任何php.ini相关设置时,请记住重新启动您的网络服务器。

A live example of using php curl_exec to do an HTTP post:使用 php curl_exec 进行 HTTP 发布的一个活生生的例子:

Put this in a file called foobar.php:把它放在一个名为 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);
?>

Then run it with the command php foobar.php , it dumps this kind of output to screen:然后使用命令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>

So you did a PHP POST to www.google.com and sent it some data.因此,您对 www.google.com 进行了 PHP POST 并向其发送了一些数据。

Had the server been programmed to read in the post variables, it could decide to do something different based upon that.如果服务器被编程为读取 post 变量,它可以根据它决定做一些不同的事情。

It's can be easily reached with:可以通过以下方式轻松实现:

<?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);

Curl Post + Error Handling + Set Headers [thanks to @mantas-d]: 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',
]);

1.Step by step 1.一步一步

  • Initialize the cURL session:初始化 cURL 会话:
$url = "www.domain.com";
$ch = curl_init($url);
  • If your request has headers like bearer token or defining JSON contents you have to set HTTPHEADER options to cURL:如果您的请求具有不记名令牌之类的标头或定义 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))
    )
);
  • If you want to include the header in the output set CURLOPT_HEADER to true :如果要在输出中包含标头,请将CURLOPT_HEADERtrue
curl_setopt($ch, CURLOPT_HEADER, false);
  • Set RETURNTRANSFER option to true to return the transfer as a string instead of outputting it directly:RETURNTRANSFER选项设置为true以将传输作为字符串返回,而不是直接输出:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  • To check the existence of a common name in the SSL peer certificate can be set to 0(to not check the names) , 1(not supported in cURL 7.28.1) , 2(default value and for production mode) :要检查 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);
  • For posting fields as an array by cURL:通过 cURL 将字段作为数组发布:
$fields = array(
    "username" => "user1",
    "password" => "passuser1",
    "gender" => 1
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
  • Execute cURL and return the string.执行 cURL 并返回字符串。 depending on your resource this returns output like result=OK :根据您的资源,这会返回类似result=OK的输出:
$result = curl_exec($ch);
  • Close cURL resource, and free up system resources:关闭 cURL 资源,释放系统资源:
curl_close($ch);

2.Use as a class 2.作为类使用

  • The whole call_cURL class that can be extended:可以扩展的整个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;
    }
}
  • Using the class and call cURL:使用类并调用 cURL:
$class = new class_name_for_call_cURL();
var_dump($class->call_cURL()); // output is true/false

3.One function 3.一个功能

  • A function for using anywhere that needed:在任何需要的地方使用的功能:
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;
}
  • This function is usable just by:此功能仅可通过以下方式使用:
var_dump(get_cURL());
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;
}

I'm surprised nobody suggested file_get_contents:我很惊讶没有人建议 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);

it's simple, it works;这很简单,它有效; I use it in an environment where I control the code at both ends.我在我控制两端代码的环境中使用它。

even better, use json_decode (and set up your code to return JSON)更好的是,使用 json_decode (并设置您的代码以返回 JSON)

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

this approach invokes curl behind the scenes, but you don't jump through as many hoops.这种方法在幕后调用 curl,但您不会跳过那么多圈。

Answer refined from this original answer elsewhere on Stack Overflow: PHP sending variables to file_get_contents()从 Stack Overflow 上其他地方的原始答案中提炼的答案: PHP 将变量发送到 file_get_contents()

If the form is using redirects, authentication, cookies, SSL (https), or anything else other than a totally open script expecting POST variables, you are going to start gnashing your teeth really quick.如果表单使用重定向、身份验证、cookies、SSL (https) 或其他任何需要 POST 变量的完全开放的脚本,那么您将很快开始咬牙切齿。 Take a look at Snoopy , which does exactly what you have in mind while removing the need to set up a lot of the overhead.看看Snoopy ,它完全符合您的想法,同时消除了设置大量开销的需要。

A simpler answer IF you are passing information to your own website is to use a SESSION variable.如果您将信息传递到自己的网站,一个更简单的答案是使用 SESSION 变量。 Begin php page with:开始 php 页面:

session_start();

If at some point there is information you want to generate in PHP and pass to the next page in the session, instead of using a POST variable, assign it to a SESSION variable.如果在某些时候您想在 PHP 中生成信息并传递到会话的下一页,而不是使用 POST 变量,请将其分配给 SESSION 变量。 Example:例子:

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

Then on the next page you simply reference this SESSION variable.然后在下一页您只需引用此 SESSION 变量。 NOTE: after you use it, be sure you destroy it, so it doesn't persist after it is used:注意:使用后,请务必将其销毁,以免在使用后持续存在:

if (isset($_SESSION['message'])) {echo $_SESSION['message']; unset($_SESSION['message']);}

Here are some boilerplate code for PHP + curl http://www.webbotsspidersscreenscrapers.com/DSP_download.php以下是 PHP + curl http://www.webbotsspidersscreenscrapers.com/DSP_download.php的一些样板代码

include in these library will simplify development包含在这些库中将简化开发

<?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, "");
    ...
?>

Examples of sending form and raw data:发送 表单原始数据的示例:

$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);

If you try to login on site with cookies.如果您尝试使用 cookie 登录网站。

This code:这段代码:

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

It May not works if you try to login, because many sites return status 200, but the post is not successful.如果您尝试登录,它可能无法正常工作,因为许多网站返回状态 200,但发布不成功。

The easy way to check if the login post is successful is to check if it setting cookies again.检查登录帖子是否成功的简单方法是检查它是否再次设置cookie。 If in output have a Set-Cookies string, this means the posts are not successful and it starts a new session.如果在输出中有一个 Set-Cookies 字符串,这意味着帖子不成功,它会启动一个新会话。

Also, the post can be successful, but the status can redirect instead of 200.此外,帖子可以成功,但状态可以重定向而不是 200。

To be sure the post is successful try this:为确保帖子成功,请尝试以下操作:

Follow location after the post, so it will go to the page where the post does redirect to:关注帖子后的位置,因此它将转到帖子重定向到的页面:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

And than check if new cookies existing in the request:然后检查请求中是否存在新的 cookie:

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

{echo 'post successful'; }

else { echo 'not successful'; }

Easiest is to send data as application/json.最简单的是将数据作为 application/json 发送。 This will take an array as input and properly encodes it into a json string:这会将数组作为输入并将其正确编码为 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM