概述

PHP支持的由Daniel Stenberg创建的libcurl库允许你与各种的服务器使用各种类型的协议进行连接和通讯。

libcurl目前支持http、https、ftp、gopher、telnet、dict、file和ldap协议。libcurl同时也支持HTTPS认证、HTTP POST、HTTP PUT、 FTP 上传(这个也能通过PHP的FTP扩展完成)、HTTP 基于表单的上传、代理、cookies和用户名+密码的认证。

PHP中使用cURL实现Get和Post请求的方法

这些函数在PHP 4.0.2中被引入。

需求

为了使用PHP的cURL函数,你需要安装 » libcurl包。

PHP需要使用libcurl 7.0.2-beta 或者更高版本。在PHP 4.2.3 里使用cURL,你需要安装7.9.0或更高版本的libcurl。从PHP 4.3.0开始你需要安装7.9.0或更高版本的libcurl。从PHP 5.0.0开始你需要安装7.10.5或更高版本的libcurl。

安装

要使用PHP的cURL支持你必须在编译PHP时加上–with-curl[=DIR] 选项,DIR为包含lib和include的目录路径。在include目录中必须有一个名为curl,包含了easy.h和curl.h的文件夹。lib文件夹里应该有一个名为libcurl.a的文件。对于PHP 4.3.0你可以配置–with-curlwrappers 使cURL使用URL流。

注意: Win32用户注意 要在Windows环境下使用这个模块,libeay32.dll和ssleay32.dll必须放到PATH环境变量包含的目录下。 不用cURL网站上的libcurl.dll。

PHP cURL 函数
以下包含了PHP cURL函数列表:

函数

描述

curl_close()

关闭一个cURL会话。

curl_copy_handle()

复制一个cURL句柄和它的所有选项。

curl_errno()

返回最后一次的错误号。

curl_error()

返回一个保护当前会话最近一次错误的字符串。

curl_escape()

返回转义字符串,对给定的字符串进行URL编码。

curl_exec()

执行一个cURL会话。

curl_file_create()

创建一个 CURLFile 对象。

curl_getinfo()

获取一个cURL连接资源句柄的信息。

curl_init()

初始化一个cURL会话。

curl_multi_add_handle()

向curl批处理会话中添加单独的curl句柄。

curl_multi_close()

关闭一组cURL句柄。

curl_multi_exec()

运行当前 cURL 句柄的子连接。

curl_multi_getcontent()

如果设置了CURLOPT_RETURNTRANSFER,则返回获取的输出的文本流。

curl_multi_info_read()

获取当前解析的cURL的相关传输信息。

curl_multi_init()

返回一个新cURL批处理句柄。

curl_multi_remove_handle()

移除curl批处理句柄资源中的某个句柄资源。

curl_multi_select()

等待所有cURL批处理中的活动连接。

curl_multi_setopt()

设置一个批处理cURL传输选项。

curl_multi_strerror()

返回描述错误码的字符串文本。

curl_pause()

暂停及恢复连接。

curl_reset()

重置libcurl的会话句柄的所有选项。

curl_setopt_array()

为cURL传输会话批量设置选项。

curl_setopt()

设置一个cURL传输选项。

curl_share_close()

关闭cURL共享句柄。

curl_share_init()

初始化cURL共享句柄。

curl_share_setopt()

设置一个共享句柄的cURL传输选项。

curl_strerror()

返回错误代码的字符串描述。

curl_unescape()

解码URL编码后的字符串。

curl_version()

获取cURL版本信息。

实例:

/*
模拟get请求
$url 链接
$headerArray 请求头
*/
function geturl($url,$headerArray =array("Content-type:application/json;","Accept:application/json")){

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch,CURLOPT_HTTPHEADER,$headerArray);
$output = curl_exec($ch);
curl_close($ch);
$output = json_decode($output,true);
return $output;
}

/*
模拟post请求
$url 链接
$headerArray 请求头
$data 请求数据
*/
function posturl($url,$data, $headerArray =array("Content-type:application/json;charset='utf-8'","Accept:application/json")){
$data = json_encode($data);

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return json_decode($output,true);
}

/*
模拟PUT请求
put=更新;
$url 链接
$headerArray 请求头
$data 请求数据
*/
function puturl($url,$data){
$data = json_encode($data);
$ch = curl_init(); //初始化CURL句柄
curl_setopt($ch, CURLOPT_URL, $url); //设置请求的URL
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); //设为TRUE把curl_exec()结果转化为字串,而不是直接输出
curl_setopt($ch, CURLOPT_CUSTOMREQUEST,"PUT"); //设置请求方式
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//设置提交的字符串
$output = curl_exec($ch);
curl_close($ch);
return json_decode($output,true);
}
/*
模拟DELETE 请求
DELETE =删除;
$url 链接
$headerArray 请求头
$data 请求数据
*/
function delurl($url,$data){
$data = json_encode($data);
$ch = curl_init();
curl_setopt ($ch,CURLOPT_URL,$put_url);
curl_setopt ($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json'));
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
$output = curl_exec($ch);
curl_close($ch);
$output = json_decode($output,true);
}
/*
模拟PATCH请求
PATCH=Http的【RFC2616】原本定义用于上传数据的方法只有POST和PUT,但是考虑到两者的不足,就增加了PATCH方法。;
$url 链接
$headerArray 请求头
$data 请求数据
*/
function patchurl($url,$data){
$data = json_encode($data);
$ch = curl_init();
curl_setopt ($ch,CURLOPT_URL,$url);
curl_setopt ($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json'));
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "PATCH");
curl_setopt($ch, CURLOPT_POSTFIELDS,$data); //20170611修改接口,用/id的方式传递,直接写在url中了
$output = curl_exec($ch);
curl_close($ch);
$output = json_decode($output);
return $output;
}

会给我们返回的信息

PHP  cURL 函数 curl类库_PHP

  • 类名称:curl
  • 1.支持单个get,post请求
  • 2.支持多个目标未登录get请求
  • 3.支持单个目标并行多个get,post请求
  • 4.支持ajax请求
  • 5.支持自定义header请求
  • 6.支持自定义编码数据请求(该情况比较特殊)
  • 7.支持代理登陆
  • 8.支持自定义来路
  • 9.支持自定义超时
  • 10.支持文件上传
<?php
/**
* 类名称:curl
* 1.支持单个get,post请求
* 2.支持多个目标未登录get请求
* 3.支持单个目标并行多个get,post请求
* 4.支持ajax请求
* 5.支持自定义header请求
* 6.支持自定义编码数据请求(该情况比较特殊)
* 7.支持代理登陆
* 8.支持自定义来路
* 9.支持自定义超时
* 10.支持文件上传
*/

/**
* demo1 get 请求
* curl()->get("http://www.baidu.com")->body();
*/

/**
* demo2 post请求
* curl()->post("http://www.xxx.com/say.php",array(
* 'data' => array(
* 'title' => 'test title',
* 'content' => 'test content',
* ),
* ))->body();
*/

/**
* demo3 post请求 ajax请求 并设置cookie
* curl()->post("http://www.xxx.com/save.php",array(
* 'data' => array(
* 'username' => 'test',
* 'password' => 'test'
* ),
* 'cookie_file' => '/tmp/cookie.txt',
* 'ajax' => 1,
* ))->body();
*/

/***
* demo4 批处理get请求
* curl()->get(array(
* 'http://www.xxx.com/test1.php?aaa=111',
* 'http://www.xxx.com/test2.php?aaa=222',
* 'http://www.xxx.com/test3.php?aaa=333',
* ))->body();
*/

/***
* demo5 批处理post请求 post请求,目前只支持单个网站的批处理post请求
* curl()->post(array(
* 'http://www.xxx.com/test1.php',
* 'http://www.xxx.com/test2.php',
* 'http://www.xxx.com/test3.php',
* ),array(
* 'data' => array(
* array(
* 'uid' => 'aabbccdd',
* ),
* array(
* 'uid' => 'eeeeeeee',
* ),
* array(
* 'uid' => 'ffffffff',
* ),
* ),
* 'cookie_file' => '/tmp/cookie.txt'
* ))->body();
*/

/**
* demo6 文件上传
* curl()->post('填写url地址',array(
* 'files' => array(
* 'pic' => '/tmp/a.gif' ,
* ),
* ))->body();
*/

/**
* 其他方法未一一列举,可查看源码进行测试
*/

class Curl {

//单例对象
private static $ins = null;

//请求结果
private $body = null;

//cookie文件
private $cookieFile = null;

//支持的请求方法
private $method = array('get','post');

//禁用初始化方法
final private function __construct()
{
}

/**
* 单例化对象
*/
public static function exec()
{
if (self::$ins) {
return self::$ins;
}
return self::$ins = new self();
}

/**
* 禁止克隆对象
*/
public function __clone()
{
throw new curlException('错误:不能克隆对象');
}

/**
* 调用不存在的方法被调用
*/
public function __call($method, $args)
{
if(!in_array($method,$this->method)) {
throw new curlException("错误:不支持{$method}方法,支持的方法有"
. join(',',$this->method));
}
return $this->request($method, $args);
}

/**
* 返回执行结果
*/
public function body()
{
return $this->body;
}

/**
* 执行请求
* @param type $method
* @param type $args
* @return 返回对象本身
*/
private function request($method, $args)
{

if (isset($args[1]['multi'])) {
$this->body = $this->multiExecCurl($method, $args);
} else {
$this->body = $this->execCurl($method, $args);
}
return $this;
}

/**
* curl 批处理请求
* @param type $method
* @param type $args
* @return type
*/
public function multiExecCurl($method, $args)
{
$urls = isset($args[0]) ? $args[0] : "";
$data = isset($args[1]['data']) ? $args[1]['data'] : "";
$ajax = isset($args[1]['ajax']) ? $args[1]['ajax'] : "";
$timeout = isset($args[1]['timeout']) ? $args[1]['timeout'] : 30;
$referer = isset($args[1]['referer']) ? $args[1]['referer'] : "";
$proxy = isset($args[1]['proxy']) ? $args[1]['proxy'] : "";
$headers = isset($args[1]['headers']) ? $args[1]['headers'] : "";

if (!is_array($urls) || (is_array($urls) && empty($urls))) {
throw new curlException("错误信息:批处理url必须是数组并且不能为空");
}

//创建批处理cURL句柄
$queue = curl_multi_init();

//取得cookie文件路径
if(!$this->cookieFile) {
$this->cookieFile = isset($args[1]['cookie_file'])
? $args[1]['cookie_file'] : "";
}

//如果未获取到浏览器环境信息,就手动指定一个
$userAgent = isset($_SERVER['HTTP_USER_AGENT'])
? $_SERVER['HTTP_USER_AGENT']
: 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:23.0) '
.'Gecko/20100101 Firefox/23.0';

//设置CURL OPT选项
$options = array(
CURLOPT_TIMEOUT => $timeout, //超时
CURLOPT_RETURNTRANSFER => 1, //输出数据流
CURLOPT_HEADER => 0, //禁止头文件数据流输出
CURLOPT_FOLLOWLOCATION => 1, //自动跳转追踪
CURLOPT_AUTOREFERER => 1, //自动设置来路信息
CURLOPT_SSL_VERIFYPEER => 0, //认证证书检查
CURLOPT_SSL_VERIFYHOST => 0, //检查SSL加密算法
CURLOPT_HEADER => 0, //禁止头文件输出
CURLOPT_NOSIGNAL => 1, //忽略php所有的传递信号
CURLOPT_USERAGENT => $userAgent,//浏览器环境字符串
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, //ipv4寻址方式
CURLOPT_ENCODING => 'gzip', //解析使用gzip压缩的网页
);

//检测是否存在代理请求
if (is_array($proxy) && !empty($proxy)) {

$options[CURLOPT_PROXY] = $proxy['host'];
$options[CURLOPT_PROXYPORT] = $proxy['port'];

$options[CURLOPT_PROXYUSERPWD] =
$proxy['user'] . ':' . $proxy['pass'];
}

//header选项
$headerOptions = array();

//模拟AJAX请求
if ($ajax) {
$headerOptions['X-Requested-With'] = 'XMLHttpRequest';
}

if ($this->cookieFile) {
$options[CURLOPT_COOKIEFILE] = $this->cookieFile;
$options[CURLOPT_COOKIEJAR] = $this->cookieFile;
}

if ($referer) {
$options[CURLOPT_REFERER] = $referer;
}

if (!empty($headerOptions)) {
$options[CURLOPT_HTTPHEADER] = $headerOptions;
}

//循环的进行初始化一个cURL会话
foreach ($urls as $k => $url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);

if ($method == 'post') {
//发送一个常规的POST请求,
//类型为:application/x-www-form-urlencoded,就像表单提交的一样
$options[CURLOPT_POST] = 1;

//使用HTTP协议中的"POST"操作来发送数据,支持键值对数组定义
//注意:即使不使用http_build_query也能自动编码
$options[CURLOPT_POSTFIELDS] = $data[$k];
}

curl_setopt_array($ch,$options);
curl_multi_add_handle($queue, $ch);
}

//初始化变量
$responses = array();
$active = null;

//循环运行当前 cURL 句柄的子连接
do {
while (($code = curl_multi_exec($queue,
$active)) == CURLM_CALL_MULTI_PERFORM);

if ($code != CURLM_OK) {
break;
}

//循环获取当前解析的cURL的相关传输信息
while ($done = curl_multi_info_read($queue)) {

//获取最后一次传输的相关信息
$info = curl_getinfo($done['handle']);

//从最后一次传输的相关信息中找 http_code 等于200
if ($info['http_code'] == 200) {
//如果设置了CURLOPT_RETURNTRANSFER,获取的输出的文本流
$responses[] = curl_multi_getcontent($done['handle']);
}

//移除curl批处理句柄资源中的某个句柄资源
curl_multi_remove_handle($queue, $done['handle']);

//关闭某个批处理句柄会话
curl_close($done['handle']);
}

if ($active > 0) {
//等待所有cURL批处理中的活动连接
curl_multi_select($queue, 0.5);
}

} while ($active);

//关闭一组cURL句柄
curl_multi_close($queue);

//返回结果
return $responses;
}

/**
* curl 单句柄请求
* @param type $method
* @param type $args
* @return type
*/
private function execCurl($method, $args)
{
//解析参数
$url = isset($args[0]) ? $args[0] : "";
$multi = isset($args[1]['multi']) ? $args[1]['multi'] : "";
$data = isset($args[1]['data']) ? $args[1]['data'] : "";
$ajax = isset($args[1]['ajax']) ? $args[1]['ajax'] : "";
$timeout = isset($args[1]['timeout']) ? $args[1]['timeout'] : 30;
$files = isset($args[1]['files']) ? $args[1]['files'] : "";
$referer = isset($args[1]['referer']) ? $args[1]['referer'] : "";
$proxy = isset($args[1]['proxy']) ? $args[1]['proxy'] : "";
$headers = isset($args[1]['headers']) ? $args[1]['headers'] : "";

//如果环境变量的浏览器信息不存在,就是用手动设置的浏览器信息
$userAgent = isset($_SERVER['HTTP_USER_AGENT'])?
$_SERVER['HTTP_USER_AGENT']:
'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:23.0)
Gecko/20100101 Firefox/23.0';

//检测url必须参数 不能为空
if (!$url) {
throw new curlException("错误:curl请求地址不能为空");
}

//设置curl选项
$options = array(
CURLOPT_URL => $url, //目标url
CURLOPT_TIMEOUT => $timeout, //超时
CURLOPT_RETURNTRANSFER => 1, //输出数据流
CURLOPT_FOLLOWLOCATION => 1, //自动跳转追踪
CURLOPT_AUTOREFERER => 1, //自动设置来路信息
CURLOPT_SSL_VERIFYPEER => 0, //认证证书检查
CURLOPT_SSL_VERIFYHOST => 0, //检查SSL加密算法
CURLOPT_HEADER => 0, //禁止头文件输出
CURLOPT_NOSIGNAL => 1, //忽略所有传递的信号
CURLOPT_USERAGENT => $userAgent,//浏览器环境字符串
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, //ipv4寻址方式
CURLOPT_ENCODING => 'gzip', //解析使用gzip压缩的网页
);

//获取cookie文件地址路径
if(!$this->cookieFile) {
$this->cookieFile = isset($args[1]['cookie_file'])
? $args[1]['cookie_file'] : "";
}

//设置代理 必须是数组并且非空
if (is_array($proxy) && !empty($proxy)) {
$options[CURLOPT_PROXY] = $proxy['host'];
$options[CURLOPT_PROXYPORT] = $proxy['port'];
$options[CURLOPT_PROXYUSERPWD] =
$proxy['user'] . ':' . $proxy['pass'];
}

//检测是否未启用自定义urlencode编码
if (!isset($args[1]['build'])) {
if ($data && $method == "post" && is_array($data)) {
$data = http_build_query($data, '', '&');
}
}

//检测是否含有上传文件
if ($files && $method == "post" && is_array($files)) {
foreach ($files as $k => $v) {
$files[$k] = '@' . $v;
}

parse_str($data, $data);
$data = $data + $files;
}

//检测判断是否是post请求
if ($method == 'post') {
//发送一个常规的POST请求
$options[CURLOPT_POST] = 1;

//使用HTTP协议中的"POST"操作来发送数据,支持键值对数组定义
$options[CURLOPT_POSTFIELDS] = $data;
}

//初始化header数组
$headerOptions = array();

//检测是否是ajax提交
if ($ajax) {
$headerOptions['X-Requested-With'] = 'XMLHttpRequest';
}


//设置cookie
if ($this->cookieFile) {
$options[CURLOPT_COOKIEFILE] = $this->cookieFile;
$options[CURLOPT_COOKIEJAR] = $this->cookieFile;
}

//设置来路
if ($referer) {
$options[CURLOPT_REFERER] = $referer;
}

//合并header
if (!empty($headers) && is_array($headers)) {
foreach ($headers as $k => $v) {
$headerOptions[$k] = $v;
}
}

//转换header选项为浏览器header格式
if (!empty($headerOptions) && is_array($headerOptions)) {
$array = array();

foreach($headerOptions as $k => $v) {
$array[] = $k . ": " . $v;
}

$options[CURLOPT_HTTPHEADER] = $array;
}

//创建curl句柄
$ch = curl_init();

//设置curl选项
curl_setopt_array($ch, $options);

//获取返回内容
$content = curl_exec($ch);

//关闭curl句柄
curl_close($ch);

//返回内容
return $content;

}

/**
* 对一个对象进行字符串echo输出
* 自动调用__toString方法
* @return type
*/
public function __toString()
{
return $this->body();
}

}

class curlException extends Exception {}

//curl方法不存在就设置一个curl方法
if (!function_exists('curl')) {
function curl() {
return curl::exec();
}
}