1. 程式人生 > 其它 >學習CURL擴充套件功能的使用(一)

學習CURL擴充套件功能的使用(一)

其實 CURL 這個擴充套件本來也不打算寫得,畢竟這個也是大家最常用的功能之一的。不過既然是在刷文件,學習到了就分享出來吧,不要陷入“知識的詛咒”。本身自己的知識體系就不完整,說不定也有很多小夥伴和我一樣只是平常追求業務快速開發而簡單地使用,並沒有深入地去了解過。今天,我們就來深入地瞭解一下 CURL 吧。

PHP 的這個 CURL 擴充套件其實是基於的 libcurl 這個系統的擴充套件軟體。在 linux 相關的系統中,這個軟體基本就是標配的,像是 CentOS 、Ubuntu 這些都是裝好系統就有的,不需要我們再單獨安裝這個 libcurl ,就算沒有的話,也可以方便地安裝到。

而對於 PHP 來說,這個擴充套件更是已經整合在了 PHP 的原始碼安裝包中,只需要我們在編譯安裝 PHP 的時候加上 --with-curl 就可以了。

使用 CURL 請求連結

先來看看最簡單地使用 CURL 來請求一個 GET 地址。

$ch = curl_init("https://www.baidu.com");

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); // 檢查證書中是否設定域名
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // 信任任何證書

$res = curl_exec($ch);
$info = curl_getinfo($ch);
if(curl_error($ch)) {
    var_dump(curl_error($ch));
}

var_dump($res);
// string(14722) "<!DOCTYPE html><!--STATUS OK-->
// <html>
// <head>
// 	<meta http-equiv="content-type" content="text/html;charset=utf-8">
// 	<meta http-equiv="X-UA-Compatible" content="IE=Edge">
// 	<link rel="dns-prefetch" href="//s1.bdstatic.com"/>
// 	<link rel="dns-prefetch" href="//t1.baidu.com"/>
// 	<link rel="dns-prefetch" href="//t2.baidu.com"/>
// 	<link rel="dns-prefetch" href="//t3.baidu.com"/>
// 	<link rel="dns-prefetch" href="//t10.baidu.com"/>
// 	<link rel="dns-prefetch" href="//t11.baidu.com"/>
// 	<link rel="dns-prefetch" href="//t12.baidu.com"/>
// 	<link rel="dns-prefetch" href="//b1.bdstatic.com"/>
// 	<title>百度一下,你就知道</title>
//  ……………………
//  ……………………
//  ……………………
// </body></html>
// "

var_dump($info);
// array(37) {
//     ["url"]=>
//     string(21) "https://www.baidu.com"
//     ["content_type"]=>
//     string(9) "text/html"
//     ["http_code"]=>
//     int(200)
//     ["header_size"]=>
//     int(960)
//     ["request_size"]=>
//     int(52)
//     ["filetime"]=>
//     int(-1)
//     ["ssl_verify_result"]=>
//     int(0)
//     ["redirect_count"]=>
//     int(0)
//     ["total_time"]=>
//     float(0.127654)
//     ["namelookup_time"]=>
//     float(0.004669)
//     ["connect_time"]=>
//     float(0.030823)
//     ["pretransfer_time"]=>
//     float(0.100782)
//     ["size_upload"]=>
//     float(0)
//     ["size_download"]=>
//     float(14722)
//     ["speed_download"]=>
//     float(115921)
//     ["speed_upload"]=>
//     float(0)
//     ["download_content_length"]=>
//     float(14722)
//     ["upload_content_length"]=>
//     float(-1)
//     ["starttransfer_time"]=>
//     float(0.127519)
//     ["redirect_time"]=>
//     float(0)
//     ["redirect_url"]=>
//     string(0) ""
//     ["primary_ip"]=>
//     string(15) "183.232.231.172"
//     ["certinfo"]=>
//     array(0) {
//     }
//     ["primary_port"]=>
//     int(443)
//     ["local_ip"]=>
//     string(13) "192.168.51.11"
//     ["local_port"]=>
//     int(52795)
//     ["http_version"]=>
//     int(2)
//     ["protocol"]=>
//     int(2)
//     ["ssl_verifyresult"]=>
//     int(0)
//     ["scheme"]=>
//     string(5) "HTTPS"
//     ["appconnect_time_us"]=>
//     int(100710)
//     ["connect_time_us"]=>
//     int(30823)
//     ["namelookup_time_us"]=>
//     int(4669)
//     ["pretransfer_time_us"]=>
//     int(100782)
//     ["redirect_time_us"]=>
//     int(0)
//     ["starttransfer_time_us"]=>
//     int(127519)
//     ["total_time_us"]=>
//     int(127654)
//   }

curl_close($ch);

標準的 CURL 套路其實就是三步。curl_init() 開啟一個控制代碼,控制代碼中包含 URL 地址,curl_exec() 執行控制代碼輸出或返回結果,curl_close() 關閉控制代碼。為什麼說 curl_exec() 是輸出或者返回結果呢?因為如果在預設的情況下,curl_exec() 是會像 phpinfo() 這類函式一樣直接列印輸出結果的,我們需要使用 curl_setopt() 設定 CURLOPT_RETURNTRANSFER 這個常量為 true 或 1 來讓 curl_exec() 將訪問結果作為返回值進行返回,而不是直接輸出。由此可以看出,curl_setopt() 也是 CURL 中非常重要的一個函式。其實它的作用就是為這個 CURL 控制代碼設定各種配置引數,包括我們在程式碼中看到的 CURLOPT_SSL_VERIFYHOST 和 CURLOPT_SSL_VERIFYPEER 就是為 HTTPS 連結的訪問而準備的配置引數,以及後面我們要看到的 POST 請求也是需要使用 curl_setopt() 來實現的。

curl_exec() 返回的是訪問的 URL 返回的結果,curl_getinfo() 返回的則是這個請求一些詳細資訊,比如我們可以看到請求的 url 地址、Content-Type 型別、http_code 等資訊,對於一些業務需求判斷來說,這些資訊非常重要。curl_error() 則是在本次請求中的錯誤資訊的顯示,如果產生了錯誤,錯誤資訊就可以通過這個函式獲取到。

POST 請求

GET 請求是非常簡單的,當然,POST 請求也不復雜,就像前面說的,只是配置引數有一些變化而已。

$ch = curl_init("http://localhost:9001");

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt_array($ch, [
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => ['a'=>'post測試'],
]);

$res = curl_exec($ch);
$info = curl_getinfo($ch);
if(curl_error($ch)) {
    var_dump(curl_error($ch));
}

var_dump($res);
// string(22) "測試資料post測試"

curl_close($ch);

在這裡,我們用了一個新的函式 curl_setopt_array() ,其實就是可以更加方便地使用陣列來定義配置引數而已,和一個一個地寫 curl_setopt() 沒有什麼區別,只是更加地方便。我們只需要指定 CURLOPT_POST 為 true 或 1,然後通過 CURLOPT_POSTFIELDS 為 POST 引數賦值就可以了,是不是也非常簡單。

CURL 的字串 URL 編碼

之前我們已經學習過一些編碼相關的函式,在 CURL 擴充套件中,也有對應的 URL 編碼函式,其實它和使用 urlencode() 並沒有什麼太大的區別。

$ch = curl_init("http://localhost:9001");
$str = "測試編碼";
$escapeStr = curl_escape($ch, $str);
var_dump($escapeStr); // string(36) "%E6%B5%8B%E8%AF%95%E7%BC%96%E7%A0%81"
var_dump(curl_unescape($ch, $escapeStr)); // string(12) "測試編碼"
curl_close($ch);

使用 curl_escape() 就可以對資料進行 URL 編碼,使用 curl_unescape() 就可以非常方便地實現解碼。不過,這兩個函式是必須要一個 CURL 控制代碼引數的,也就是說,它們不能脫離 CURL 來直接使用。我們日常開發還是使用 urlencode() 這類更為通用的函式就好了。

檢視 CURL 的版本號

最後,我們再學習一個非常簡單的函式,就是檢視一下當前系統的 CURL 版本情況以及一些相關的軟體資訊,比如支援的協議列表之類的內容。

var_dump(curl_version());
// array(16) {
//     ["version_number"]=>
//     int(475648)
//     ["age"]=>
//     int(5)
//     ["features"]=>
//     int(11519901)
//     ["ssl_version_number"]=>
//     int(0)
//     ["version"]=>
//     string(6) "7.66.0"
//     ["host"]=>
//     string(25) "x86_64-apple-darwin19.5.0"
//     ["ssl_version"]=>
//     string(14) "OpenSSL/1.1.1d"
//     ["libz_version"]=>
//     string(6) "1.2.11"
//     ["protocols"]=>
//     array(23) {
//       [0]=>
//       string(4) "dict"
//       [1]=>
//       string(4) "file"
//       [2]=>
//       string(3) "ftp"
//       [3]=>
//       string(4) "ftps"
//       [4]=>
//       string(6) "gopher"
//       [5]=>
//       string(4) "http"
//       [6]=>
//       string(5) "https"
//       [7]=>
//       string(4) "imap"
//       [8]=>
//       string(5) "imaps"
//       [9]=>
//       string(4) "ldap"
//       [10]=>
//       string(5) "ldaps"
//       [11]=>
//       string(4) "pop3"
//       [12]=>
//       string(5) "pop3s"
//       [13]=>
//       string(4) "rtmp"
//       [14]=>
//       string(4) "rtsp"
//       [15]=>
//       string(3) "scp"
//       [16]=>
//       string(4) "sftp"
//       [17]=>
//       string(3) "smb"
//       [18]=>
//       string(4) "smbs"
//       [19]=>
//       string(4) "smtp"
//       [20]=>
//       string(5) "smtps"
//       [21]=>
//       string(6) "telnet"
//       [22]=>
//       string(4) "tftp"
//     }
//     ["ares"]=>
//     string(6) "1.15.0"
//     ["ares_num"]=>
//     int(69376)
//     ["libidn"]=>
//     string(5) "2.2.0"
//     ["iconv_ver_num"]=>
//     int(0)
//     ["libssh_version"]=>
//     string(13) "libssh2/1.9.0"
//     ["brotli_ver_num"]=>
//     int(16777223)
//     ["brotli_version"]=>
//     string(5) "1.0.7"
//   }

總結

就像文章開頭所說的,CURL 的內容其實並不複雜,核心的就那幾步,它最複雜的部分是在於非常多的配置常量資訊,而且這些資訊並不是太好記,掌握常用的就可以了,後面我們還將繼續講解 CURL 中其它的內容,不要錯過哦。

測試程式碼:https://github.com/zhangyue0503/dev-blog/blob/master/php/2021/02/source/4.學習CURL擴充套件功能的使用(一).php

參考文件:

https://www.php.net/manual/zh/ref.curl.php