打造自用 curl 类

xyj2156 PHP 2018-04-23

大纲

  1. 实现可用功能
  2. 明白自己使用方式
  3. 使用方便
  4. 获取结果方便

实现功能

弄一个可以使用的类 原型

以下代码就可以实现一个 curl 的功能

代码:

class Curl
{
    protected $ch = '';
    protected $log= [];
    protected $debug= true;
    protected $data= [];

    public function request()
    {
        $url = 'http://blog.xyj2156.top';
        $data = [];
        $ch = curl_init();
        $this -> ch = $ch;
        $this -> debug && $this -> log[] = '开始设置请求公共数据。';
        curl_setopt($this -> ch, CURLOPT_URL, $this -> option['url']);
        curl_setopt($this -> ch, CURLOPT_SSL_VERIFYPEER, false);  
        curl_setopt($this -> ch, CURLOPT_SSL_VERIFYHOST, false); 

        curl_setopt($this -> ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($this -> ch, CURLOPT_HEADER, 1);
        curl_setopt($this -> ch, CURLOPT_TIMEOUT, $this -> timeout);
        $this -> debug && $this -> log[] = '设置请求公共数据完成。';
        $tmp = curl_exec($this -> ch);
        return $tmp;
    }
}

明白自己的使用方式

为了让自己用起来舒服, 添加了很多额外部分。

添加昨天使用的 数组转对象后 可以对象方式并能数组方式同时访问,方便获取,同时可以转换回来

地址 https://blog.xyj2156.top/posts/php_array_converted_object_and_array

  1. 添加 各种适合自己的方法
  2. 各种魔术方法
  3. 调用起来各种方便
  4. 获取支持对象调用 数组调用 转换成数组等方法

最终 是下面这个代码了。

    namespace Curl;
    use \Curl\CurlBody;
    use \Curl\CurlHeader;
    use \Curl\CurlCookie;

    class Curl
    {
        protected $isPost = false;
        protected $debug = true;
        protected $log = [];
        protected $ch = null;
        protected $option = [];
        protected $timeout = 10;
        protected $error = '';
        protected $errorno = 0;
        protected $response = [
            'cookie' => '',
            'result' => '',
            'header' => '',
            'body' => ''
        ];

        public function __construct($url = null, $data = null)
        {
            $this -> debug && $this -> log[] = '构造对象';
            $this -> ch = curl_init();
            if(!is_null($url) && preg_match('/^https?:\/\/[\w\.]+[^\.]\/?[\w\#\?=]?$/', $url)){
                $this -> option ['url'] = $url;
            }
            $this -> data($data);
        }

        public function post($data = null)
        {
            $this -> debug && $this -> log[] = '设置 post 数据。'.var_export($data, true);
            $this -> isPost = true;
            return $this -> data($data);
        }

        public function data($data){
            if(empty($this -> option ['data'])){
                $this -> option ['data'] = [];
            }
            if(!is_null($data)){
                if(is_array($data)){
                    $tmp = $data;
                } else if(is_string($data) && preg_match('/([^\&]+=[^\&]*)/', $data)){
                    parse_str($data, $tmp);
                }
                if(isset($tmp))
                    $this -> option ['data'] = array_merge($this -> option ['data'], $tmp);
                $this -> debug && $this -> log[] = '设置数据完成。';
            }
            return $this;
        }

        public function get($data = null)
        {
            $this -> debug && $this -> log[] = '设置 get 数据。';
            $this -> isPost = false;
            return $this -> data($data);
        }

        public function cookie ($cookie = null)
        {
            if(empty($this -> option ['cookie'])){
                $this -> option ['cookie'] = [];
            }
            if(!is_null($cookie)){
                if(is_array($cookie)){
                    $tmp = $cookie;
                } else if (is_string($cookie)){
                    parse_str($data, $tmp);
                }
                if( isset ($tmp))
                    $this -> option['cookie'] = array_merge($this -> option['cookie'], $tmp);
            }
            return $this;
        }

        public function request()
        {
            if (empty($this -> option)) {
                $this ->debug && $this -> log[] = '由于没有 option 导致 调用 request 直接返回 this';
                $this -> error = '您没有设置任何选项';
                return $this;
            }
            if (empty($this -> option['url']) || !is_string($this -> option['url'])) {
                $this -> error = '您没有正确设置 URL url是:'.var_export($this -> option['url'], 1);
                return $this;
            }
            if (empty($this -> ch)) {
                $this -> ch = curl_init();
            }

            $this -> setOpt();

            if($this -> isPost){
                curl_setopt($this -> ch, CURLOPT_POST, true);
                if(!empty($this -> option['data'])){
                    curl_setopt($this -> ch, CURLOPT_POSTFIELDS, $this -> option['data']);
                }
            } else {
                curl_setopt($this -> ch, CURLOPT_POST, false);
                if(!empty($this -> option['data'])){
                    $param = http_build_query( $this -> option['data'] );
                    curl_setopt($this -> ch, CURLOPT_URL, $this -> option['url'].'?'.$param);
                }
            }

            if(!empty($this -> option['cookie']) || (isset($this -> response) && isset($this -> response['cookie']) && is_array($this -> response['cookie']))){
                empty($this -> option['cookie']) && ($this -> option['cookie'] = []);
                $this -> option['cookie'] = array_merge($this -> option['cookie'], $this -> response['cookie']);
                $cookie = http_build_query($this -> option['cookie']);
                $cookie = str_replace('&', ';', $cookie);
                curl_setopt($this -> ch, CURLOPT_COOKIE, $cookie);
            }
            if(!empty($this -> option['header'])){
                curl_setopt($this -> ch, CURLOPT_HTTPHEADER, $this -> option['header']);
            }
            $this -> option = [];
            
            $tmp = curl_exec($this -> ch);
            $this -> response['result'] = $tmp;
            $this -> error = curl_error($this -> ch);
            $this -> errorno = curl_errno($this -> ch);
            return $this -> parseResponse($tmp);
        }

        public function __get($name)
        {
            $this -> debug && $this -> log[] = "由于 获取 {$name} 导致调用魔术方法 get 。";
            switch ($name) {
                case 'result':
                case 'content':
                case 'body' :
                case 'cookie':
                case 'header':
                case 'response':
                    $this -> request();
                    switch ($name) {
                        case 'result':
                        case 'content':
                            return $this -> response['result'];
                        case 'body' :
                            return $this -> response['body'];
                        case 'cookie':
                            return $this -> response['cookie'];
                        case 'header':
                            return $this -> response['header'];
                        case 'response':
                            return $this -> response;
                    }
                case 'option':
                    return $this -> option;
                case 'error':
                    return $this -> error;
                case 'url':
                    return $this -> option['url'];
                default:
                    return $this;
            }
            return $this;
        }

        public function __set($name, $value)
        {
            $this -> debug && $this -> log[] = "由于 设置 {$name} 导致调用魔术方法 set 值是".var_export($value, true);
            switch ($name) {
                case 'method':
                    if(strtolower($value) == 'post'){
                        $this -> isPost = true;
                    } else {
                        $this -> isPost = false;
                    }
                    break;
                case 'cookie' :
                    if($value){
                        $this -> option['cookie'] = $value;
                    }
                    break;
                case 'data' :
                    if($value){
                        $this -> data($value);
                    }
                    break;
                case 'url' :
                    if($value){
                        $this -> option['url'] = ($value);
                    }
                    break;
                case 'header' :
                    if($value){
                        $this -> option['header'] = ($value);
                    }
                    break;
            }
            return $this;
        }

        private function setOpt()
        {
            $this -> debug && $this -> log[] = '开始设置请求公共数据。';
            curl_setopt($this -> ch, CURLOPT_URL, $this -> option['url']);
            curl_setopt($this -> ch, CURLOPT_SSL_VERIFYPEER, false);  
            curl_setopt($this -> ch, CURLOPT_SSL_VERIFYHOST, false); 

            curl_setopt($this -> ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($this -> ch, CURLOPT_HEADER, 1);
            curl_setopt($this -> ch, CURLOPT_TIMEOUT, $this -> timeout);
            $this -> debug && $this -> log[] = '设置请求公共数据完成。';
        }

        private function parseResponse($raw)
        {
            $this -> debug && $this -> log[] = '开始 处理 返回的数据';
            if($raw){
                $tmp = explode("\r\n\r\n", $raw);
                $body = array_pop($tmp);
                $header = array_pop($tmp);
                $re = preg_match_all("/(?:set\-cookie:([^\r\n=]+)=([^\r\n;]*);)/i", $header, $matches);
                $cookie = [];
                if($re && !empty($matches) && !empty($matches[1]) && !empty($matches[2])){
                    foreach ($matches[1] as $k => $v) {
                        $a = !empty($matches[2][$k]);
                        $cookie[$v] = $a ? $matches[2][$k] : '';
                    }
                }

                $tmpH = explode("\r\n", $header);
                foreach ($tmpH as $v) {
                    $tmp = preg_split('/[:;]/', $v, 2);
                    $a = array_shift($tmp);
                    $b = array_shift($tmp);
                    if(!$b){
                        $tmp = explode(' ', $a, 2);
                        $a = array_shift($tmp);
                        $b = array_shift($tmp);
                    }
                    $tmpH[$a] = $b;
                }

                $cookieObj = new CurlCookie($cookie);

                $tmpH['Set-Cookie'] = $cookieObj;

                $json = json_decode($body, 1);

                $this -> response['header'] = new CurlHeader($tmpH);
                $this -> response['body'] = $json ? new CurlBody($json) : $body;
                $this -> response['cookie'] = $cookieObj;
            } else {
                $this -> response['header'] = '';
                $this -> response['body'] = '';
                $this -> response['cookie'] = '';
            }
            $this -> debug && $this -> log[] = '返回数据处理完成。';
            return $this;
        }

        public function __call($name, $value){
            $this -> debug && $this -> log[] = "调用 {$name} 引起 魔术方法 call 值:".var_export($value, true);
            switch ($name) {
                case 'url':
                    $this -> option['url'] = array_shift($value);
                    break;
                case 'error' :
                    return $this -> error;
            }
            return $this;
        }

        private function __clone(){}
    }

关于使用方便

上面的类写的一些魔术方法,自我感觉使用还是挺方便的。

比如:

  • post(['a' => 1]) 这样就能实现 post 方式请求地址。应该还有不足,比如:put show delete 等,都没有实现。
  • get(['a' => 1]) 这样能用get方式请求。
  • post('a=1&b=2') 这样也能请求。而且 支持多次调用 post(['a' => 1]) -> post('b=2&c=3') -> post(['d' => 4]) -> data('e=5')
  • 设置 $obj -> data = ['aa' => 11]->data(['aa' => 11]) 功能完全一样。
  • 有一点就是post还是get 以最后一个为准。

获取更方便

  • 返回结果是 json 的时候,返回结果中所有的内容可以用对象方式获取,也可以用数组方式获取,也可以混合获取,还支持 任意一级变成数组 直接在后面使用 -> toArray()就可以了。
    xml 没有解析。(待续……)
PREV
PHP 实现 数组转换成可以遍历的对象,既可以使用数组方式访问,又可以按照之前的数组形式访问
NEXT
半路出家搞个Svn 版本库

评论(0)

评论已关闭