抛出问题

  • 问题1:日常开发中,咱们都会遇到接口类的申请,各种各样的第三方接口,以及外部接口等,大家都是怎么方便快捷的保护这些接口的疾速申请呢?
  • 问题2:面对第三方的接口,对接的时候记得,后续查找会不会感觉找不到在哪了呢?或者查找归类比拟麻烦呢?
  • 问题3:相似的第三方接口,你是否写反复的办法调用和处理结果呢?
  • ……

如果你有下面的相似问题,是否会思考优化呢?也就是把几户一样的接口做成配置化,不论是调用还是前期保护都比拟不便呢?本着“不便别人,造福本人”的开发准则,必须从优解决,安顿!

API接口例子

// 接口1地址: $url = 'https://www.test.com/api/test';参数: $param = array('id' => 1, 'code' => '123', 'status' => 1);返回: array('code' => 200, 'msg' => '');// 接口2地址: $url = 'https://www.test.com/api/test2';参数: $param = array('type' => 1, 'num' => '');返回: array('code' => 200, 'msg' => '');// 接口N

针对下面的两个接口,如果做成配置化的申请,也就是,写好对立的申请入口,对于后续新增同样接口,只须要依据格局配置接口地址以及申请参数即可。

接口申请类设计准则

  1. 繁多入口
  2. 接口信息可配置化
  3. 对立校验接口参数,避免非法参数申请
  4. 对立的申请办法和解决
  5. 接口返回数据格式统一
  6. ……

申请类的繁多入口

繁多入口是指每个接口申请,公共申请这个办法即可,此办法须要传配置的接口键的值,以及申请参数等,具体能够看代码里的正文阐明。

/** * 接口申请入口 * @param string $action 配置的接口键名 * @param array $param 申请参数 * @param bool $is_format 是否格式化申请后果 * @param bool $debug 是否开启调试模式 * @return array|string 返回申请后果 */public static function request($action = '', $param = array(), $is_format = true, $debug = false){    // 初始化    self::initParam();    // 校验参数,并设置申请参数    $check = self::setApiParam($action, $param);    if (!$check) {        return self::$result;    }    // 发动接口申请    $response = self::curlByPost(self::$url, self::$param, self::$token, self::$type);    // 无需格式化间接返回    if (!$is_format) {        return $response;    }    // 设置返回值    self::setResult($response);    // 是否调试输入申请信息    if ($debug) {        self::echo_msg("url: " . self::$url);        self::echo_msg("token: " . self::$token);        self::echo_msg("param: " . json_encode(self::$param));        self::echo_msg("response: " . $response);    }    return self::$result;}

配置接口信息

下面的2个接口,间接做成配置化的模式,此配置api_config的键的名字能够自定义,最好命名为接口的阐明,url为接口地址,type为Content-Type的类型抉择,param就是接口参数,具体的参数配置看正文即可。

// 接口地址,申请形式,参数的配置// 1. required:是否必传(true为必传,false为选传)// 2. default:可设置默认值,不传值时取// 3. range:可设置传值范畴,只可传范畴内的值// 其余可自在批改进行扩大private static $api_config = array(    // 测试接口1配置    'test_1' => array(        'url' => 'https://www.test.com/api/test',        'type' => 'x-www-form-urlencoded',        'param' => array(            'id' => array('required' => true, 'default' => 1),            'code' => array('required' => true),            'status' => array('required' => true, 'range' => array(1, 2))        )    ),    // 测试接口2配置    'test_2' => array(        'url' => 'https://www.test.com/api/test2',        'type' => 'form-data',        'param' => array(            'type' => array('required' => true, 'default' => 1),            'num' => array('required' => false)        )    ),);

校验参数

依据配置的参数,进行校验申请传入的参数是否无效,能够无效过滤局部非法参数

/** * 设置接口申请的参数和地址等申请信息 * @param string $action 配置的接口键名 * @param array $param 申请参数 * @return bool 返回虚实 */public static function setApiParam($action = '', $param = array()){    // 查看接口办法是否已配置    if (!isset(self::$api_config[$action])) {        self::$result['msg'] = '接口未配置';        return false;    }    // 获取接口配置    $api_info = self::$api_config[$action];    $api_param = $api_info['param'];    // 循环校验参数    foreach ($api_param as $key => $config) {        if (!isset($param[$key])) {            // 字段未传            if ($config['required'] && !isset($config['default'])) {                // 必传,并且没有默认值则报错                self::$result['msg'] = '参数[' . $key . ']必传';                return false;            }            // 非必传,取默认值            isset($config['default']) && self::$param[$key] = $config['default'];        } else {            // 字段已传            self::$param[$key] = $param[$key];        }        // 判断是否在取值范畴内        if (self::$param[$key] && isset($config['range'])) {            if (!in_array(self::$param[$key], $config['range'])) {                // 不在取值范畴内                self::$result['msg'] = '参数[' . $key . ']的值不在取值范畴内';                return false;            }        }    }    // 如果须要获取token密钥,此办法须要to-do,如果其余签名形式可依据理论批改    self::$token = self::getToken();    // 接口地址    if (empty($api_info['url'])) {        self::$result['msg'] = '接口地址为空';        return false;    }    self::$url = $api_info['url'];    // Content-Type申请类型    if (!isset(self::$headers[$api_info['type']])) {        self::$result['msg'] = '无此申请类型';        return false;    }    self::$type = $api_info['type'];    return true;}

残缺源码

下面说的三点为外围局部,可能看起来有点云里雾里的感觉,我必定不是那种不将就的人,残缺的源码必须安顿上,如有写到不到位或者不全的,请不要吐槽我啦,你懂的。

<?php/** * Created by PhpStorm. * User: gxcuizy * Date: 2021/02/20 * Time: 下午 13:18 * api接口申请封装类 * Class ApiRequest */class ApiRequest{    // 接口地址    private static $url = '';    // 申请header类型    private static $type = '';    // 接口密钥    private static $token = '';    // 申请参数    private static $param = array();    // 返回数组格局    private static $result = array(        'code' => 0,        'msg' => '',        'data' => array()    );    // header头类型数组    private static $headers = array(        '' => array(),        'form-data' => array('Content-Type: multipart/form-data'),        'x-www-form-urlencoded' => array('Content-Type:application/x-www-form-urlencoded'),        'json' => array('Content-Type: application/json'),    );    // 接口地址,申请形式,参数的配置    // 1. required:是否必传(true为必传,false为选传)    // 2. default:可设置默认值,不传值时取    // 3. range:可设置传值范畴,只可传范畴内的值    // 其余可自在批改进行扩大    private static $api_config = array(        // 测试接口1配置        'test_1' => array(            'url' => 'https://www.test.com/api/test',            'type' => 'x-www-form-urlencoded',            'param' => array(                'id' => array('required' => true, 'default' => 1),                'code' => array('required' => true),                'status' => array('required' => true, 'range' => array(1, 2))            )        ),        // 测试接口2配置        'test_2' => array(            'url' => 'https://www.test.com/api/test2',            'type' => 'form-data',            'param' => array(                'type' => array('required' => true, 'default' => 1),                'num' => array('required' => false)            )        ),    );    /**     * 接口申请入口     * @param string $action 配置的接口键名     * @param array $param 申请参数     * @param bool $is_format 是否格式化申请后果     * @param bool $debug 是否开启调试模式     * @return array|string 返回申请后果     */    public static function request($action = '', $param = array(), $is_format = true, $debug = false)    {        // 初始化        self::initParam();        // 校验参数,并设置申请参数        $check = self::setApiParam($action, $param);        if (!$check) {            return self::$result;        }        // 发动接口申请        $response = self::curlByPost(self::$url, self::$param, self::$token, self::$type);        // 无需格式化间接返回        if (!$is_format) {            return $response;        }        // 设置返回值        self::setResult($response);        // 是否调试输入申请信息        if ($debug) {            self::echo_msg("url: " . self::$url);            self::echo_msg("token: " . self::$token);            self::echo_msg("param: " . json_encode(self::$param));            self::echo_msg("response: " . $response);        }        return self::$result;    }    /**     * 初始化参数值     */    private static function initParam()    {        self::$url = '';        self::$type = '';        self::$token = '';        self::$param = array();        self::$result['code'] = 0;        self::$result['msg'] = '';        self::$result['data'] = array();    }    /**     * 设置接口申请的参数和地址等申请信息     * @param string $action 配置的接口键名     * @param array $param 申请参数     * @return bool 返回虚实     */    public static function setApiParam($action = '', $param = array())    {        // 查看接口办法是否已配置        if (!isset(self::$api_config[$action])) {            self::$result['msg'] = '接口未配置';            return false;        }        // 获取接口配置        $api_info = self::$api_config[$action];        $api_param = $api_info['param'];        // 循环校验参数        foreach ($api_param as $key => $config) {            if (!isset($param[$key])) {                // 字段未传                if ($config['required'] && !isset($config['default'])) {                    // 必传,并且没有默认值则报错                    self::$result['msg'] = '参数[' . $key . ']必传';                    return false;                }                // 非必传,取默认值                isset($config['default']) && self::$param[$key] = $config['default'];            } else {                // 字段已传                self::$param[$key] = $param[$key];            }            // 判断是否在取值范畴内            if (self::$param[$key] && isset($config['range'])) {                if (!in_array(self::$param[$key], $config['range'])) {                    // 不在取值范畴内                    self::$result['msg'] = '参数[' . $key . ']的值不在取值范畴内';                    return false;                }            }        }        // 如果须要获取token密钥,此办法须要to-do,如果其余签名形式可依据理论批改        self::$token = self::getToken();        // 接口地址        if (empty($api_info['url'])) {            self::$result['msg'] = '接口地址为空';            return false;        }        self::$url = $api_info['url'];        // Content-Type申请类型        if (!isset(self::$headers[$api_info['type']])) {            self::$result['msg'] = '无此申请类型';            return false;        }        self::$type = $api_info['type'];        return true;    }    /**     * POST申请     * @param string $url 接口地址     * @param array $data 申请参数     * @param string $token 密钥token     * @param string $type 传参类型     * @param array $header_ext 扩大的header信息     * @return bool|string 返回申请后果     */    private static function curlByPost($url = '', $data = array(), $token = '', $type = 'json', $header_ext = array())    {        $header = self::$headers[$type];        // 是否须要token        if ($token) {            $header[] = "Authorization:$token";        }        // 扩大的header信息        if (!empty($header_ext)) {            $header = array_merge($header, $header_ext);        }        // 发送POST申请        $ch = curl_init();        curl_setopt($ch, CURLOPT_POST, 1);        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);        curl_setopt($ch, CURLOPT_HEADER, 0);        curl_setopt($ch, CURLOPT_URL, $url);        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);        $output = curl_exec($ch);        curl_close($ch);        return $output;    }    /**     * 解决接口响应返回     * @param string $response 接口返回数据     */    private static function setResult($response = '')    {        if ($response) {            // 有返回值            $result = json_decode($response, true);            if (isset($result['code']) && $result['code'] == 200) {                // 申请胜利                self::$result['data'] = $result['data'];                self::$result['code'] = 200;            } else {                // 申请失败                if (isset($result['code'])) {                    self::$result['code'] = $result['code'];                }                self::$result['msg'] = $response;            }        } else {            // 无返回值异样            self::$result['msg'] = "empty response.";        }    }    /**     * 获取密钥token(TODO)     * @return string     */    private static function getToken()    {        $token = '';        return $token;    }    /**     * 打印输出信息     * @param string $msg 输入文本     */    private static function echo_msg($msg = '')    {        if (!empty($msg)) {            $msg = "[" . date("Y-m-d H:i:s") . "] " . $msg . PHP_EOL;            echo $msg;            @ob_flush();            @flush();        }    }}

最初

刚过完春节,大家预计都还没缓过劲来进入Coding状态,恭祝大家在新的一年里可能播种多多,播种满满,2021所想皆能实现。如果大家有什么好的想法或者倡议,也能够底部留言给我哈,感激哦!