with - php curl post json




PHP+curl, HTTP POST sample code? (7)

Can anyone show me how to do a php curl with an HTTP POST?

I want to send data like this:

username=user1, password=passuser1, gender=1

To www.domain.com

I expect the curl to return a response like result=OK. Are there any examples?


A live example of using php curl_exec to do an HTTP post:

Put this in a file called 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:

<!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.

Had the server been programmed to read in the post variables, it could decide to do something different based upon that.


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
namespace MyApp\Http;

class Curl
{
    /** @var resource cURL handle */
    private $ch;

    /** @var mixed The response */
    private $response = false;

    /**
     * @param string $url
     * @param array  $options
     */
    public function __construct($url, array $options = array())
    {
        $this->ch = curl_init($url);

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

        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
    }

    /**
     * Get the response
     * @return string
     * @throws \RuntimeException On cURL error
     */
    public function getResponse()
    {
         if ($this->response) {
             return $this->response;
         }

        $response = curl_exec($this->ch);
        $error    = curl_error($this->ch);
        $errno    = curl_errno($this->ch);

        if (is_resource($this->ch)) {
            curl_close($this->ch);
        }

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

        return $this->response = $response;
    }

    /**
     * Let echo out the response
     * @return string
     */
    public function __toString()
    {
        return $this->getResponse();
    }
}

// usage
$curl = new \MyApp\Http\Curl('http://www.example.com', array(
    CURLOPT_POSTFIELDS => array('username' => 'user1')
));

try {
    echo $curl;
} catch (\RuntimeException $ex) {
    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. Then you can always swap this implementation with another adapter of your like, without any side effects to your application.

Using HTTPS / encrypting traffic

Usually there's a problem with cURL in PHP under the Windows operating system. While trying to connect to a https protected endpoint, you will get an error telling you that 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);). 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:

; 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. When changing any php.ini related settings remember to restart your webserver.


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

Here are some boilerplate code for 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, "");
    ...
?>

If you try to login on site with cookies.

This code:

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

May not works if you try to login, because many sites returns status 200, but the post is not successful.

Easy way to check if the login post is successful is check if it setting cookies again. If in output have Set-Cookies string, this means the posts is not successful and it starts new session.

Also the post can be successful, but the status can be redirect instead 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 do redirect to:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

And than check if new cookies existing in the request:

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

{echo 'post successful'; }

else { echo 'not successful'; }

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

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);
    if (curl_error($ch)) {
        throw new \Exception(curl_error($ch));
    }
    curl_close($ch);

    return $response;
}




http-post