PHP cURL請求詳解

在PHP後端的開發過程當中,除了獲取數據庫的數據和處理數據的內部邏輯,每每還須要請求其餘服務器接口的數據,咱們通常有3種方式來獲取數據,分別是:php

  1. file_get_contents
  2. fsockopen
  3. curl

3種經常使用的接口獲取方式簡述

file_get_contents

函數聲明:html

/** 函數做用:將整個文件讀入字符串
    @param $filename 讀取的文件名或url,若是是文件路徑,$use_include_path需置爲true
    @param $use_include_path 是否使用文件目錄路徑查找,若是是文件查找,須要置爲true,默認爲false
    @param $context 資源參數,使用stream_context_create創造的一個上下文,用於配置讀取文件的參數,如配置HTTP請求的方法和頭部信息
    @param $offset 開始讀取數據的偏移值
    @param $maxlen 從$offset開始獲取多長的數據
    @return string 若是成功返回字符串,失敗返回false
*/
string file_get_contents(string $filename, bool $use_include_path = false, resource $context, int $offset = -1, int $maxlen)

實例獲取數據:前端

// 筆者開發使用Yii2,因此路由控制器使用action的寫法
public function actionFetch() {
    // 該url爲筆者寫的另一篇文章,測試用
    $data = file_get_contents('https://segmentfault.com/a/1190000011549088');
    // 獲取到的數據須要輸出咱們才能在前端請求看到返回的結果
    echo $data;
    // 結束本次請求
    return $data;
}

fsockopen

函數聲明:數據庫

/** 函數做用:打開一個網絡鏈接或者一個Unix套接字鏈接
    @param $hostname 初始化套接字鏈接到的主機
    @param $port 端口號,若是不傳遞,則不實用端口
    @param $errno 
    @param $errstr 字符串形式的錯誤信息
    @param $timeout 超時時間,單位爲s
    @return resource 若是成功返回文件句柄,可使用文件函數讀寫,失敗返回false
*/
resource fsockopen(string $hostname, int $port = -1, int &$errno, string &$errstr, float $timeout = ini_get("default_socket_timeout"))

實例獲取數據:json

注意:在個人測試環境中報錯:`Unable to find the socket transport "http" - did you
forget to enable it when you configured
PHP?`,是因爲php.ini配置問題,因此不推薦此種方法獲取,由於受配置文件影響,很容易不可用。
// 筆者開發使用Yii2,因此路由控制器使用action的寫法
$fp = fsockopen('https://segmentfault.com/a/1190000011549088', 80);
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
    $out = "GET / HTTP/1.1\r\n";
    $out .= "Host: www.example.com\r\n";
    $out .= "Connection: Close\r\n\r\n";
    fwrite($fp, $out);
    while (!feof($fp)) {
        echo fgets($fp, 128);
    }
    fclose($fp);
}

cURL

須要安裝 libcurl包。
cURL全稱 commandLine Uniform Resource Locator,命令行統一資源定位器,用於在命令行上傳和下載url文件。提供用於程序開發的 libcurl包。

實例獲取數據:segmentfault

// 初始化一個curl資源
$ch = curl_init('https://segmentfault.com/a/1190000011549088');
// 執行該curl對象,返回結果
$data = curl_exec($ch);
// 關閉cURL資源,釋放系統資源
curl_close($ch);

3種方式的優劣對比

在代碼風格上,file_get_contents最爲簡潔,fsockopencurl比較複雜。後端

在配置頭部信息上:
file_get_contents經過stream_context_set_option() 來配置頭部信息;
fsockopen能夠經過fwirte ($socket, $config)的方式或字符串拼接配置請求頭部信息,支持異步請求;
curl能夠經過curl_setopt($curl, $name, $key)的方式配置請求配置,做爲lib庫,功能強大。數組

PHP不支持多進程,若是須要異步請求,非阻塞的方式,請選擇fsockopen
常規的請求咱們使用file_get_contentscurl,除了功能外,下面作一個性能測試:服務器

$url = 'https://segmentfault.com/a/1190000011549088';

// 100次file_get_contents請求,結果爲113s
$start = time();
for ($i = 0; $i < 100; $i++) {
    $data = file_get_contents($url);
}
$end = time();
$cost = $end - $start;
echo 'file_get_contents 100次總耗時:', "$cost";

// 100次curl請求,結果爲48s
$start = time();
for ($i = 0; $i < 100; $i++) {
    $ch = curl_init($url);
    // 設置不直接輸出結果,而是保存到$data中
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $data = curl_exec($ch);
}
$end = time();
$cost = $end - $start;
echo 'curl 100次總耗時:', "$cost";

因此,在常規PHP請求中,咱們使用curl的方式來請求接口數據。cookie

cURL詳解

curl的基本使用方法就是:

  1. curl_init()初始化cURL會話
  2. curl_setopt()curl_setopt_array()設置配置選項
  3. curl_exec()執行會話
  4. curl_close()關閉會話

curl_init()

函數聲明:

/** 函數做用:初始化curl會話
    @param $url 配置中的請求url,若是不傳遞,須要在curl_setopt()設置CURLOPT_URL
    @return resource 若是成功返回cURL句柄,失敗返回false
*/
resource curl_init([string $url = NULL])

curl_setopt()curl_setopt_array()

函數聲明:

/** 函數做用:設置cURL傳輸選項
    @param $ch curl_init()返回的cURL句柄
    @param $option 須要設置的CURLOPT_XXX選項
    @param $value 在option選項上設置的值
    @return bool 成功返回true,失敗返回false
*/
bool curl_setopt(resource $ch, int $option, mixed $value)

/** 函數做用:設置cURL傳輸選項
    @param $ch curl_init()返回的cURL句柄
    @param $options 須要設置的CURLOPT_XXX選項和值的數組
    @return bool 所有成功返回true,一個失敗馬上返回false
*/
bool curl_setopt_array(resource $ch, array $options)

使用實例:

// 設置url和不直接輸出結果,單項設置
curl_setopt($ch, CURLOPT_URL, 'https://segmentfault.com/a/1190000011549088');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

// 批量設置
curl_setopt_array($ch, array(
    CURLOPT_URL => 'https://segmentfault.com/a/1190000011549088',
    CURLOPT_RETURNTRANSFER => true
));

CURLOPT_參數

列舉一些經常使用的參數,所有參數能夠在 PHP curl參數文檔 查閱。

  • CURLOPT_HEADER 啓用時會將頭文件的信息做爲數據流輸出。
  • CURLOPT_POST TRUE 時會發送 POST 請求,類型爲:application/x-www-form-urlencoded,是 HTML 表單提交時最多見的一種。
  • CURLOPT_RETURNTRANSFER TRUE 將curl_exec()獲取的信息以字符串返回,而不是直接輸出。
  • CURLOPT_UPLOAD TRUE 準備上傳。
  • CURLOPT_CONNECTTIMEOUT 在嘗試鏈接時等待的秒數。設置爲0,則無限等待。
  • CURLOPT_PORT 用來指定鏈接端口。
  • CURLOPT_TIMEOUT 容許 cURL 函數執行的最長秒數。
  • CURLOPT_COOKIE 設定 HTTP 請求中"Cookie: "部分的內容。多個 cookie 用分號分隔,分號後帶一個空格(例如, "fruit=apple; colour=red")。
  • CURLOPT_POSTFIELDS 所有數據使用HTTP協議中的 "POST" 操做來發送。該參數只支持一維數組,若是須要傳遞多維數組,須要使用http_build_query處理,更詳細的信息能夠查看PHP cURL請求中CURLOPT_POSTFIELDS只支持一維數組這篇文章。
  • CURLOPT_URL 須要獲取的 URL 地址,也能夠在curl_init() 初始化會話的時候。

curl_exec()

函數聲明:

/** 函數做用:執行curl會話
    @param $ch curl_init()返回的cURL句柄
    @return mixed 成功返回true,失敗返回false;若是設置了CURLOPT_RETRUNTRANSFER爲ture,成功返回執行結果
*/
mixed curl_exec(resource $ch)

curl_close()

函數聲明:

/** 函數做用:關閉curl會話
    @param $ch curl_init()返回的cURL句柄
    @return void
*/
void curl_close(resource $ch)

curl請求封裝

public static function parseApi($vars = Array(), $timeout = 60, $uri = '') {
    // 初始化curl
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $uri);
    // 支持POST請求
    curl_setopt($ch, CURLOPT_POST, 1);
    // 不直接輸出,返回到變量
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    // 設置POST參數
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($vars));
    // 設置超時,防止機器被大量超時請求卡死
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    // 請求數據
    $response = curl_exec($ch);
    // 關閉請求
    curl_close($ch);
    // 對數據進行編碼,方便先後端數據處理
    $result = json_decode($response, true);
    // PHP返回數據
    return $result;
}

PHP cURL並行請求

除了上面的curl_init以外,cURL還支持curl_multi_init並行請求,容許咱們同時請求上百個接口,而不是foreach輪詢阻塞式的請求。詳細的能夠查看個人另外一篇文章:PHP實現併發請求

總結

若是你須要非阻塞的請求,可使用fsockopen()方法。
常規的使用curl來請求,功能強大,使用方便,按需配置。

參考資料

  1. PHP手冊 file_get_contents: http://php.net/manual/zh/func...
  2. PHP手冊 stream_context_create: http://php.net/manual/zh/func...
  3. PHP手冊 fsockopen: http://php.net/manual/zh/func...
  4. 百度百科 curl: https://baike.baidu.com/item/...
  5. 維基百科 curl: https://zh.wikipedia.org/wiki...
  6. PHP手冊 curl函數:http://php.net/manual/zh/ref....
  7. 博客園 fsockopen實現異步請求:http://www.cnblogs.com/52fhy/...
相關文章
相關標籤/搜索