PHP + ikal, kode sampel HTTP POST?

491

Adakah yang bisa menunjukkan kepada saya bagaimana melakukan php curl dengan HTTP POST?

Saya ingin mengirim data seperti ini:

username=user1, password=passuser1, gender=1

Untuk www.domain.com

Saya berharap ikal akan mengembalikan respons seperti result=OK. Apakah ada contoh?

mysqllearner
sumber

Jawaban:

840
<?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 { ... }
?>
miku
sumber
47
tidak perlu digunakan http_build_query()untuk menangani parameter; cukup lewati array ke CURLOPT_POSTFIELDScukup.
Raptor
8
@Raptor yang menyediakan array langsung ke CURLOPT_POSTFIELDS sebenarnya curl membuat jenis POST yang sedikit berbeda. (Harapkan: 100-lanjut)
Oleg Popov
22
Juga jika nilai CURLOPT_POSTFIELDSarray, Content-Typeheader akan ditetapkan multipart/form-datasebagai ganti application/x-www-form-urlencoded. php.net/manual/en/function.curl-setopt.php
Chloe
2
Menggunakan CURLOPT_RETURNTRANSFER berarti curl_exec akan mengembalikan respons sebagai string daripada mengeluarkannya.
bnp887
2
Saya sarankan menggunakan, truebukan 1untuk CURLOPT_POST.
FluorescentGreen5
261

Prosedural

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

Berorientasi pada objek

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

Pemakaian

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

Catatan di sini: akan lebih baik untuk membuat beberapa jenis antarmuka yang disebut AdapterInterfacemisalnya dengan getResponse()metode dan biarkan kelas di atas mengimplementasikannya. Kemudian Anda selalu dapat menukar implementasi ini dengan adaptor lain seperti Anda, tanpa efek samping pada aplikasi Anda.

Menggunakan HTTPS / mengenkripsi lalu lintas

Biasanya ada masalah dengan cURL di PHP di bawah sistem operasi Windows. Saat mencoba terhubung ke titik akhir terproteksi https, Anda akan mendapatkan pesan kesalahan tentang hal itu certificate verify failed.

Apa yang dilakukan kebanyakan orang di sini adalah memberi tahu perpustakaan CURL untuk mengabaikan saja kesalahan sertifikat dan melanjutkan ( curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);). Karena ini akan membuat kode Anda berfungsi, Anda memperkenalkan lubang keamanan besar dan memungkinkan pengguna jahat untuk melakukan berbagai serangan pada aplikasi Anda seperti serangan Man In The Middle atau semacamnya.

Tidak pernah melakukan itu. Sebagai gantinya, Anda hanya perlu memodifikasi php.inidan memberi tahu PHP di mana CA Certificatefile Anda membiarkannya memverifikasi sertifikat dengan benar:

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

Yang terbaru cacert.pemdapat diunduh dari Internet atau diekstrak dari browser favorit Anda . Saat mengubah php.inipengaturan terkait, ingatlah untuk memulai kembali server web Anda.

emix
sumber
4
Ini harus benar-benar menjadi jawaban yang diterima, karena praktik terbaik adalah membiarkan perpustakaan HTTP menangani pengodean variabel Anda.
Eric Seastrand
4
Ini tidak selalu terjadi. Saya telah melihat server web yang mengharapkan variabel POST dikodekan dengan cara tertentu, menyebabkan mereka gagal. Menurut saya http_build_query () sebenarnya lebih andal daripada cURL untuk ini.
César
4
Spesifikasi HTTP cukup jelas tentang bagaimana seharusnya parameter POST. Perangkat webserver harus memenuhi standar.
emix
1
Dengan menggunakan cara ini, Anda akan memaksa CURL untuk menggunakan jenis POST yang sedikit berbeda. (Harapkan: 100-lanjut). Lihat artikel ini: support.urbanairship.com/entries/…
Oleg Popov
5
Memperluas komentar @ César, dokumentasi PHP secara eksplisit mencatat yang berikut: "Melewati array ke CURLOPT_POSTFIELDS akan menyandikan data sebagai multi-bagian / formulir-data , sementara meneruskan string yang dikodekan-URL akan menyandikan data sebagai aplikasi / x-www-form -dijalankan . " Saya baru-baru ini menghabiskan banyak waktu mencoba memecahkan masalah mengapa panggilan CURL gagal pada titik akhir pihak ketiga hanya untuk akhirnya menyadari bahwa mereka tidak mendukung multi-data / formulir-data.
Jake Z
31

Contoh langsung menggunakan php curl_exec untuk melakukan posting HTTP:

Masukkan ini ke dalam file bernama 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);
?>

Kemudian jalankan dengan perintah php foobar.php, ini akan menampilkan output seperti ini ke layar:

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

Jadi Anda melakukan POST PHP ke www.google.com dan mengirimkannya beberapa data.

Seandainya server diprogram untuk membaca variabel post, ia dapat memutuskan untuk melakukan sesuatu yang berbeda berdasarkan itu.

Eric Leschinski
sumber
$postvars .= $key . $value;harus $postvars .= $key . $value ."&";atau tidak?
Manwal
Melihat lagi jawaban ini, Anda juga dapat mengganti implementasi konverter string kueri khusus Anda dengan http_build_query , berikan saja $fieldsarray dan itu akan menghasilkan string kueri.
Ketahuilah bahwa Anda harus menyandikan data Anda agar data dapat dikirimkan dengan aman.
wtf8_decode
3
Oh tidak, jangan mencoba membuat string posting sendiri! gunakan ini:curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields));
oriadam
3
-1 karena Anda tidak lolos vars posting Anda. Contoh OP adalah mengirimkan nama pengguna dan kata sandi yang dikirimkan pengguna untuk otentikasi. Dengan solusi Anda, pengguna dengan & di kata sandi mereka tidak akan pernah bisa masuk. Komentar oriadam benar, tetapi Anda dapat keluar http_build_queryseperti:curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
Eric Seastrand
26

Itu dapat dengan mudah dicapai dengan:

<?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);
V. Kovpak
sumber
13

Curl Post + Penanganan Kesalahan + Set Header [terima kasih kepada @ 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',
]);
MSS
sumber
Kode Anda tidak akan menutup pegangan dan sumber daya gratis, karena Anda curl_close setelah melemparkan pengecualian. Anda harus curl_close di dalam blok akhirnya.
emix
7
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;
}
Mantas D
sumber
1
Kode Anda tidak akan menutup pegangan dan sumber daya gratis, karena Anda curl_close setelah melemparkan pengecualian. Anda harus curl_closeberada di dalam finallyblok.
emix
6

Jika formulir menggunakan pengalihan, otentikasi, cookie, SSL (https), atau apa pun selain skrip yang benar-benar terbuka yang mengharapkan variabel POST, Anda akan mulai menggertakkan gigi dengan sangat cepat. Lihatlah Snoopy , yang melakukan apa yang ada dalam pikiran Anda sambil menghilangkan kebutuhan untuk mengatur banyak overhead.

Anthony
sumber
Jika Anda ingin tetap menggunakan lib saham, coba tambahkancurl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
MarkHu
Satu-satunya downside adalah bahwa Anda masih harus berurusan dengan pengaturan toples cookie dan masalah potensial lainnya (seperti apakah akan mengikuti arahan ulang, cara menangani otentikasi non-berbasis HTTP, dll). 6 tahun kemudian, saya akan merekomendasikan konsep "browser tanpa kepala" yang lebih umum daripada perpustakaan tertentu (atau apa pun di sourceforge, tanggal berapa, kan?) Dan sementara saya umumnya hanya berurusan dengan opsi curl secara langsung, saya masih akan menyarankan melihat perpustakaan tanpa kepala-browser yang kompatibel dengan PSR-7 (Guzzle adalah satu-satunya yang saya tahu begitu saja) untuk menghindari sakit kepala.
Anthony
3

Jawaban yang lebih sederhana JIKA Anda menyampaikan informasi ke situs web Anda sendiri adalah dengan menggunakan variabel SESI. Mulailah halaman php dengan:

session_start();

Jika pada titik tertentu ada informasi yang ingin Anda hasilkan dalam PHP dan diteruskan ke halaman berikutnya dalam sesi, alih-alih menggunakan variabel POST, tetapkan ke variabel SESSION. Contoh:

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

Kemudian pada halaman berikutnya Anda cukup merujuk variabel SESI ini. CATATAN: setelah Anda menggunakannya, pastikan Anda menghancurkannya, jadi itu tidak bertahan setelah digunakan:

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

Berikut adalah beberapa kode boilerplate untuk PHP + curl http://www.webbotsspidersscreenscrapers.com/DSP_download.php

termasuk dalam perpustakaan ini akan menyederhanakan pengembangan

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

Jika Anda mencoba masuk di situs dengan cookie.

Kode ini:

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

Mungkin tidak berfungsi jika Anda mencoba masuk, karena banyak situs mengembalikan status 200, tetapi posnya tidak berhasil.

Cara mudah untuk memeriksa apakah posting login berhasil adalah memeriksa apakah pengaturan cookie lagi. Jika dalam output memiliki string Set-Cookies, ini berarti posting tidak berhasil dan memulai sesi baru.

Juga posting dapat berhasil, tetapi statusnya dapat diarahkan bukan 200.

Untuk memastikan posting berhasil coba ini:

Ikuti lokasi setelah posting, jadi itu akan pergi ke halaman di mana posting melakukan redirect ke:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

Dan daripada memeriksa apakah ada cookie baru dalam permintaan:

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

{echo 'post successful'; }

else { echo 'not successful'; }
Atanas Atanasov
sumber
1

Contoh pengiriman formulir dan data mentah :

$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);
Serhii Andriichuk
sumber