PHP + curl, HTTP POST โค้ดตัวอย่าง?


491

ทุกคนสามารถแสดงวิธีทำ php curl ด้วย HTTP POST ได้ไหม

ฉันต้องการส่งข้อมูลเช่นนี้:

username=user1, password=passuser1, gender=1

ถึง www.domain.com

result=OKผมคาดว่าขดที่จะกลับมาตอบสนองเหมือน มีตัวอย่างอะไรบ้าง?

คำตอบ:


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

47
ไม่จำเป็นต้องใช้http_build_query()เพื่อจัดการพารามิเตอร์ เพียงผ่านอาร์เรย์ไปCURLOPT_POSTFIELDSก็พอ
Raptor

8
@Raptor ให้อาร์เรย์โดยตรงกับ CURLOPT_POSTFIELDS จริง ๆ แล้ว curl ทำให้ POST แตกต่างกันเล็กน้อย (คาดหวัง: 100 ต่อไป)
Oleg Popov

22
นอกจากนี้หากค่าของCURLOPT_POSTFIELDSเป็นอาร์เรย์ที่Content-Typeส่วนหัวจะถูกกำหนดให้แทนmultipart/form-data php.net/manual/th/function.curl-setopt.phpapplication/x-www-form-urlencoded
Chloe

2
การใช้ CURLOPT_RETURNTRANSFER หมายความว่า curl_exec จะส่งคืนการตอบสนองเป็นสตริงแทนที่จะแสดงผลลัพธ์
bnp887

2
ผมขอแนะนำให้ใช้trueแทนสำหรับ1 CURLOPT_POST
FluorescentGreen5

261

ขั้นตอน

// 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 / เข้ารหัสการรับส่งข้อมูล

มักจะมีปัญหากับ cURL ใน PHP ภายใต้ระบบปฏิบัติการ Windows ในขณะที่พยายามที่จะเชื่อมต่อไปยังปลายทาง https certificate verify failedป้องกันคุณจะได้รับข้อผิดพลาดบอกคุณว่า

สิ่งที่คนส่วนใหญ่ทำที่นี่คือบอกไลบรารี cURL ให้ละเว้นข้อผิดพลาดใบรับรองและดำเนินการต่อ ( curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);) เนื่องจากจะทำให้โค้ดของคุณใช้งานได้คุณแนะนำช่องโหว่ความปลอดภัยขนาดใหญ่และทำให้ผู้ใช้ที่ประสงค์ร้ายสามารถโจมตีแอปต่าง ๆ เช่นMan In The Middle Attack หรือ

ไม่เคยทำเช่นนั้น แต่คุณเพียงแค่ต้องแก้ไขphp.iniและบอก PHP ว่าCA Certificateไฟล์ของคุณอยู่ที่ไหนเพื่อให้มันตรวจสอบใบรับรองอย่างถูกต้อง:

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

ล่าสุดcacert.pemสามารถดาวน์โหลดได้จากอินเทอร์เน็ตหรือสกัดจากเบราว์เซอร์ที่คุณชื่นชอบ เมื่อเปลี่ยนการphp.iniตั้งค่าที่เกี่ยวข้องอย่าลืมรีสตาร์ทเว็บเซิร์ฟเวอร์ของคุณ


4
นี่ควรเป็นคำตอบที่ได้รับการยอมรับจริง ๆ เพราะแนวปฏิบัติที่ดีที่สุดคือให้ไลบรารี HTTP จัดการการเข้ารหัสตัวแปรของคุณ
Eric Seastrand

4
นี่ไม่ใช่กรณีเสมอไป ฉันเห็นเว็บเซิร์ฟเวอร์ที่คาดว่าตัวแปร POST จะได้รับการเข้ารหัสในบางวิธีทำให้พวกเขาล้มเหลวอย่างอื่น สำหรับฉันแล้วดูเหมือนว่า http_build_query () น่าเชื่อถือกว่า cURL สำหรับเรื่องนี้
César

4
ข้อมูลจำเพาะ HTTP ค่อนข้างตรงไปตรงมาเกี่ยวกับลักษณะของพารามิเตอร์ POST ซอฟต์แวร์เว็บเซิร์ฟเวอร์ควรเป็นไปตามมาตรฐานอยู่แล้ว
emix

1
ด้วยการใช้วิธีนี้คุณจะบังคับให้ cURL ใช้โพสต์ประเภทต่าง ๆ เล็กน้อย (คาดว่า: 100 ต่อไป) ตรวจสอบบทความนี้: support.urbanairship.com/entries/…
Oleg Popov

5
เมื่อขยายความคิดเห็นของ @ César เอกสาร PHP จะบันทึกต่อไปนี้อย่างชัดเจน: "การส่งอาร์เรย์ไปยัง CURLOPT_POSTFIELDS จะเข้ารหัสข้อมูลเป็นmultipart / form-dataขณะที่ผ่านสตริงที่เข้ารหัส URL จะเข้ารหัสข้อมูลเป็นแอปพลิเคชัน / x-www-form -urlencoded . " ฉันเพิ่งใช้เวลามากเกินไปในการพยายามแก้ไขปัญหาว่าทำไมการเรียก cURL จึงล้มเหลวในจุดปลายของบุคคลที่สามเท่านั้นในที่สุดก็ตระหนักได้ว่าพวกเขาไม่สนับสนุนหลายส่วน / แบบฟอร์มข้อมูล
Jake Z

31

ตัวอย่างจริงของการใช้ php curl_exec เพื่อทำการโพสต์ HTTP:

วางสิ่งนี้ในไฟล์ชื่อ 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 และส่งข้อมูลไปให้

หากเซิร์ฟเวอร์ถูกโปรแกรมให้อ่านในตัวแปรโพสต์ก็สามารถตัดสินใจที่จะทำสิ่งที่แตกต่างตามที่


$postvars .= $key . $value;ควร$postvars .= $key . $value ."&";หรือไม่
Manwal

ดูอีกครั้งที่คำตอบนี้คุณยังสามารถแทนที่การใช้ตัวแปลงสตริงข้อความค้นหาแบบกำหนดเองด้วยhttp_build_queryเพียงแค่กำหนด$fieldsอาร์เรย์และมันจะส่งออกสตริงข้อความค้นหา

โปรดทราบว่าคุณควรเข้ารหัสข้อมูลของคุณเพื่อให้สามารถส่งได้อย่างปลอดภัย
wtf8_decode

3
โอ้ไม่ลองสร้างสตริงโพสต์ด้วยตัวเอง! ใช้สิ่งนี้:curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields));
oriadam

3
-1 เนื่องจากคุณไม่ได้หนีจากการโพสต์ vars ตัวอย่างของ OP กำลังส่งชื่อผู้ใช้และรหัสผ่านที่ผู้ใช้ส่งเพื่อตรวจสอบความถูกต้อง ด้วยวิธีการแก้ปัญหาของคุณผู้ใช้ที่มี & ในรหัสผ่านของพวกเขาจะไม่สามารถเข้าสู่ระบบความคิดเห็นของ oriadam ถูกต้อง แต่คุณสามารถออกจากhttp_build_queryเช่น:curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
Eric Seastrand

26

สามารถเข้าถึงได้ง่ายด้วย:

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

13

โพสต์ Curl + จัดการข้อผิดพลาด + ตั้งส่วนหัว [ขอบคุณ @ 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',
]);

รหัสของคุณจะไม่ปิดตัวจัดการและแหล่งข้อมูลฟรีเนื่องจากคุณ curl_close หลังจากมีข้อผิดพลาด คุณควร curl_close ภายในบล็อคสุดท้าย
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;
}

1
รหัสของคุณจะไม่ปิดตัวจัดการและแหล่งข้อมูลฟรีเนื่องจากคุณ curl_close หลังจากมีข้อผิดพลาด คุณควรcurl_closeอยู่ในfinallyบล็อก
emix

6

หากแบบฟอร์มนั้นใช้การเปลี่ยนเส้นทางการรับรองความถูกต้องคุกกี้ SSL (https) หรือสิ่งอื่นใดนอกจากสคริปต์แบบเปิดทั้งหมดที่คาดว่าจะมีตัวแปร POST คุณจะต้องเริ่มกัดฟันอย่างรวดเร็วจริงๆ ลองดูSnoopyซึ่งทำสิ่งที่คุณมีอยู่ในใจในขณะที่ไม่จำเป็นต้องตั้งค่าโสหุ้ยมากมาย


หากคุณต้องการที่จะยึดติดกับ lib หุ้นเพียงแค่ลองเพิ่มcurl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
MarkHu

ข้อเสียเพียงอย่างเดียวคือคุณยังต้องจัดการกับการตั้งค่าโถคุกกี้และปัญหาอื่น ๆ ที่อาจเกิดขึ้น (เช่นว่าจะติดตามการเปลี่ยนเส้นทางวิธีจัดการกับการตรวจสอบความถูกต้องโดยใช้ HTTP ไม่ใช่ ฯลฯ ) 6 ปีต่อมาฉันขอแนะนำแนวคิดทั่วไปของ "หัวขาด - เบราว์เซอร์" แทนที่จะเป็นห้องสมุดเฉพาะ (หรืออะไรก็ตามบน sourceforge ลงวันที่ถูกต้อง?) และในขณะที่ฉันมักจะจัดการกับตัวเลือก curl โดยตรงฉันยังคงแนะนำ มองไปที่ไลบรารี่ของเบราว์เซอร์ที่ไม่มีหัวต่อที่รองรับPSR-7 (Guzzle เป็นอันเดียวที่ฉันรู้ว่ามีอยู่ในมือ) เพื่อหลีกเลี่ยงอาการปวดหัว
Anthony

3

คำตอบที่ง่ายกว่าหากคุณส่งข้อมูลไปยังเว็บไซต์ของคุณเองคือใช้ตัวแปร 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']);}

3

นี่คือตัวอย่างรหัสสำเร็จรูปสำหรับ PHP + curl http://www.webbotsspidersscreenscrapers.com/DSP_download.php

รวมไว้ในห้องสมุดเหล่านี้จะทำให้การพัฒนาง่ายขึ้น

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

2

หากคุณพยายามเข้าสู่ระบบเว็บไซต์ด้วยคุกกี้

รหัสนี้:

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

อาจไม่ทำงานหากคุณพยายามเข้าสู่ระบบเนื่องจากหลายเว็บไซต์ส่งคืนสถานะ 200 แต่โพสต์ไม่สำเร็จ

วิธีง่าย ๆ ในการตรวจสอบว่าโพสต์ล็อกอินสำเร็จหรือไม่คือตรวจสอบว่าตั้งค่าคุกกี้อีกครั้งหรือไม่ หากในเอาต์พุตมีสตริง Set-Cookies หมายความว่าโพสต์ไม่สำเร็จและเริ่มเซสชันใหม่

โพสต์ยังสามารถประสบความสำเร็จ แต่สถานะสามารถเปลี่ยนเส้นทางแทน 200

เพื่อให้แน่ใจว่าโพสต์นั้นประสบความสำเร็จลองสิ่งนี้:

ติดตามตำแหน่งหลังโพสต์ดังนั้นมันจะไปยังหน้าที่โพสต์เปลี่ยนเส้นทางไปที่:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

และกว่าการตรวจสอบว่ามีคุกกี้ใหม่ในคำขอหรือไม่:

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

{echo 'post successful'; }

else { echo 'not successful'; }

1

ตัวอย่างของการส่งแบบฟอร์มและข้อมูลดิบ :

$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);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.