curl_multi 多并发访问 封装

/**
 * curl_multi_do   并发
 * 通过curl请求一个url,data为k=v&k1=v1的格式(数组时自动整理)或post一个xml数据
 * $parameters[$url, $data, $method, $param] 对应curl_do
 **/
function curl_multi_do($parameters = []){
    $result = [];
    $ch_arr = [];
    $mh = curl_multi_init();
    // 如果使用证书则在$cert参数传入包含证书cert.pem和私钥key.pem的文件夹路径
    foreach ($parameters as $parameter) {
        $url = $parameter['url'];
        $data = $parameter['data'];
        $method = $parameter['method'];
        $param = $parameter['param'];

        if(!isset($param['cookie'])){ $param['cookie'] = false; }
        if(!isset($param['header'])){ $param['header'] = false; }
        if(!isset($param['timeout'])){ $param['timeout'] = 10; }
        if(!isset($param['need_header'])){ $param['need_header'] = false; }
        if(!isset($param['cert'])){ $param['cert'] = false; }

        $ch = curl_init();
        switch($method){
            case 'GET':
                if(is_array($data)){
                    $data_str = '';
                    if(count($data) !== 0){
                        foreach($data as $k => $v){
                            $data_str .= '&'.$k.'='.urlencode($v);
                        }
                        $data_str = substr($data_str,1);
                    }
                }else{
                    $data_str = &$data;
                }
                curl_setopt($ch,CURLOPT_URL,$url.($data_str === '' ? '' : '?'.$data_str));
                break;
            case 'POST':
                curl_setopt($ch,CURLOPT_URL,$url);
                curl_setopt($ch,CURLOPT_POST,true);
                curl_setopt($ch,CURLOPT_POSTFIELDS,$data);
                break;
            case 'PUT':
            case 'DELETE':
                curl_setopt($ch,CURLOPT_URL,$url);
                curl_setopt($ch,CURLOPT_CUSTOMREQUEST,$method);
                curl_setopt($ch,CURLOPT_POSTFIELDS,$data);
                break;
        }

        if($param['cert'] !== false){    // 如果使用证书
            // 证书和证书路径
            curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLCERT,$param['cert'].'cert.pem');
            // 私钥和私钥路径
            curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLKEY,$param['cert'].'key.pem');
        }

        if(substr($url,0,5) === 'https'){    // 如果是ssl安全请求
            curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
            curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
        }

        // 如果设置cookie
        if($param['cookie'] !== false){
            if(is_array($param['cookie'])){
                $cookie_str = '';
                if(count($param['cookie']) !== 0){
                    foreach($param['cookie'] as $k => $v){
                        $cookie_str .= '; '.$k.'='.$v;
                    }
                    $cookie_str = substr($cookie_str,2);
                }
                $param['cookie'] = $cookie_str;
            }
            curl_setopt($ch,CURLOPT_COOKIE,$param['cookie']);
        }

        // 如果设置header
        if($param['header'] !== false){
            curl_setopt($ch,CURLOPT_HTTPHEADER,$param['header']);
        }

        curl_setopt($ch,CURLOPT_HEADER,$param['need_header']); // 将头文件的信息作为数据流输出
        curl_setopt($ch,CURLOPT_TIMEOUT,$param['timeout']);
        curl_setopt($ch,CURLOPT_ENCODING,'');
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);    // 要求结果为字符串且输出到屏幕

        curl_multi_add_handle($mh,$ch);
        $ch_arr[] = $ch;
    }

    $active = null;
    //execute the handles
    do {
        $mrc = curl_multi_exec($mh, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);

    while ($active && $mrc == CURLM_OK) {
        if (curl_multi_select($mh) != -1) {
            do {
                $mrc = curl_multi_exec($mh, $active);
            } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        }
    }

    foreach ($ch_arr as $ch) {
        $rt = [];
        $rt[1] = curl_multi_getcontent($ch);
        $rt[0] = curl_getinfo($ch,CURLINFO_HTTP_CODE);
        $rt[2] = $url;
        $rt[3] = $method;
        $rt[4] = $data;
        $rt[5] = curl_errno($ch);
        $result[] = $rt;
        curl_multi_remove_handle($mh, $ch);
    }
    curl_multi_close($mh);
    return $result;
}
原文地址:https://www.cnblogs.com/tingfengqieyu/p/8393481.html