Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Api often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Api, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
12 | class Api |
||
13 | { |
||
14 | private static $error = ''; // 错误信息; |
||
15 | private static $selfInstanceMap = []; // 实例列表; |
||
16 | private static $postQueryStr = []; // post数据时 需要携带的查询字符串 |
||
17 | |||
18 | private static $CACHE_DRIVER = ''; // 接口缓存驱动类名 |
||
19 | |||
20 | private static $apiData; //返回的数据 |
||
21 | |||
22 | private static $API_URL; // 微信接口地址 |
||
23 | |||
24 | private static $APP_ID; // 应用ID; |
||
25 | private static $APP_SECRET; // 应用密钥; |
||
26 | |||
27 | private static $ORIGINAL_ID; // 原始ID; |
||
28 | |||
29 | private static $TOKEN; //TOKEN |
||
30 | private static $ENCODING_AES_KEY; //ENCODING_AES_KEY |
||
31 | |||
32 | /** |
||
33 | * 接口初始化, 必须执行此方法才可以使用接口. |
||
34 | * |
||
35 | * @param string $appid |
||
36 | * @param string $appsecret 服务号APP_SECRET |
||
37 | * @param string $originalid 服务号ORIGINAL_ID |
||
38 | * @param string $token 服务号TOKEN |
||
39 | * @param string $encoding_aes_key 服务号ENCODING_AES_KEY |
||
40 | * @param string $apiurl 微信接口地址 APIURL |
||
41 | * @param string $cacheDriver 缓存驱动 Redis File ThinkPHP ...... |
||
42 | */ |
||
43 | View Code Duplication | public static function init($appid, $appsecret, $originalid = '', $token, $encoding_aes_key, $apiurl = 'https://api.weixin.qq.com/', $cacheDriver = 'File') |
|
|
|||
44 | { |
||
45 | self::$API_URL = $apiurl ? $apiurl : 'https://api.weixin.qq.com/'; |
||
46 | self::$APP_ID = $appid; |
||
47 | self::$APP_SECRET = $appsecret; |
||
48 | self::$ORIGINAL_ID = $originalid; |
||
49 | self::$TOKEN = $token; |
||
50 | self::$ENCODING_AES_KEY = $encoding_aes_key; |
||
51 | self::$CACHE_DRIVER = $cacheDriver; |
||
52 | } |
||
53 | |||
54 | /** |
||
55 | * 工厂+多例模式 获取接口实例. |
||
56 | * |
||
57 | * @author Tian |
||
58 | * |
||
59 | * @date 2015-12-08 |
||
60 | * |
||
61 | * @param string $className 接口类名. |
||
62 | * |
||
63 | * @return object |
||
64 | */ |
||
65 | public static function factory($className) |
||
66 | { |
||
67 | if (!$className || !is_string($className)) { |
||
68 | exit('类名参数不正确'); |
||
69 | } |
||
70 | |||
71 | $className = __NAMESPACE__ . '\\API\\' . $className . 'Api'; |
||
72 | |||
73 | View Code Duplication | if (!array_key_exists($className, self::$selfInstanceMap)) { |
|
74 | $api = new $className(); |
||
75 | if (!$api instanceof BaseApi) { |
||
76 | exit($className . ' 必须继承 BaseApi'); |
||
77 | } |
||
78 | self::$selfInstanceMap[$className] = $api; |
||
79 | } |
||
80 | |||
81 | return self::$selfInstanceMap[$className]; |
||
82 | } |
||
83 | |||
84 | /** |
||
85 | * 设置错误信息. |
||
86 | * |
||
87 | * @author Tian |
||
88 | * |
||
89 | * @date 2015-12-08 |
||
90 | * |
||
91 | * @param string $errorText 错误信息 |
||
92 | */ |
||
93 | public static function setError($errorText) |
||
94 | { |
||
95 | self::$error = $errorText; |
||
96 | } |
||
97 | |||
98 | /** |
||
99 | * 获取错误信息. |
||
100 | * |
||
101 | * @author Tian |
||
102 | * |
||
103 | * @date 2015-12-08 |
||
104 | * |
||
105 | * @return string |
||
106 | */ |
||
107 | public static function getError() |
||
108 | { |
||
109 | return self::$error; |
||
110 | } |
||
111 | |||
112 | /** |
||
113 | * 设置api原始返回值 |
||
114 | * |
||
115 | * @param $apiData |
||
116 | */ |
||
117 | public static function setApiData($apiData) |
||
121 | |||
122 | /** |
||
123 | * 获取api原始返回值 |
||
124 | * |
||
125 | * @return array |
||
126 | */ |
||
127 | public static function getApiData() |
||
131 | |||
132 | /** |
||
133 | * 设置post操作的get参数. |
||
134 | * |
||
135 | * @author Tian |
||
136 | * |
||
137 | * @date 2015-08-03 |
||
138 | * |
||
139 | * @param string $name 参数名 |
||
140 | * @param string $value 值 |
||
141 | */ |
||
142 | public static function setPostQueryStr($name, $value) |
||
146 | |||
147 | /** |
||
148 | * 设置API_URL参数. |
||
149 | * |
||
150 | * @author Tian |
||
151 | * |
||
152 | * @date 2015-08-03 |
||
153 | * |
||
154 | * @param string $url 参数名 |
||
155 | */ |
||
156 | public static function setApiUrl($url) |
||
160 | |||
161 | /** |
||
162 | * 获取允许访问的token. |
||
163 | * |
||
164 | * @author Tian |
||
165 | * |
||
166 | * @param bool $jus 强制刷新 |
||
167 | * |
||
168 | * @date 2015-12-08 |
||
169 | * |
||
170 | * @return string |
||
171 | */ |
||
172 | public static function getAccessToken($jus = false) |
||
198 | |||
199 | /** |
||
200 | * 获取微信服务器ip. |
||
201 | * |
||
202 | * @author Tian |
||
203 | * |
||
204 | * @date 2015-12-08 |
||
205 | * |
||
206 | * @return array |
||
207 | */ |
||
208 | |||
209 | View Code Duplication | public static function getWxIpList() |
|
210 | { |
||
211 | $module = 'getcallbackip'; |
||
212 | $queryStr = []; |
||
213 | $res = self::_get($module, '', $queryStr); |
||
214 | if (!$res) { |
||
215 | exit(self::getError()); |
||
216 | } |
||
217 | |||
218 | return $res; |
||
219 | } |
||
220 | |||
221 | /** |
||
222 | * 获取AppId |
||
223 | * |
||
224 | * @return string AppId |
||
225 | */ |
||
226 | public static function getAppId() |
||
230 | |||
231 | /** |
||
232 | * 获取ENCODING_AES_KEY |
||
233 | * |
||
234 | * @return string ENCODING_AES_KEY |
||
235 | */ |
||
236 | public static function getEncoding_Aes_Key() |
||
240 | |||
241 | /** |
||
242 | * 获取TOKEN |
||
243 | * |
||
244 | * @return string TOKEN |
||
245 | */ |
||
246 | public static function getToken() |
||
250 | |||
251 | /** |
||
252 | * 获取AppSecret |
||
253 | * |
||
254 | * @return string AppSecret |
||
255 | */ |
||
256 | public static function getAppSecret() |
||
260 | |||
261 | /** |
||
262 | * 用get的方式访问接口. |
||
263 | * |
||
264 | * @author Tian |
||
265 | * |
||
266 | * @date 2015-12-08 |
||
267 | * |
||
268 | * @param string $module 指定接口模块 |
||
269 | * @param string $node 指定接口模块的节点 |
||
270 | * @param array $queryStr 查询字符串 |
||
271 | * @param bool $arsort 是否排序 |
||
272 | * @param string $apitype Api类型 |
||
273 | * |
||
274 | * @return array|bool 错误时返回false |
||
275 | */ |
||
276 | View Code Duplication | public static function _get($module, $node, $queryStr = [], $arsort = true, $apitype = 'cgi-bin') |
|
338 | |||
339 | /** |
||
340 | * 用post的方式访问接口. |
||
341 | * |
||
342 | * @author Tian |
||
343 | * |
||
344 | * @date 2015-12-08 |
||
345 | * |
||
346 | * @param string $module 指定接口模块 |
||
347 | * @param string $node 指定接口模块的节点 |
||
348 | * @param array $data 要发送的数据 |
||
349 | * @param bool $jsonEncode 是否转换为jsons数据 |
||
350 | * @param string $apitype Api类型 |
||
351 | * |
||
352 | * @return array|bool 错误时返回false; |
||
353 | */ |
||
354 | public static function _post($module, $node, $data, $jsonEncode = true, $apitype = 'cgi-bin') |
||
431 | |||
432 | //token 刷新后重试 post |
||
433 | View Code Duplication | public static function post_retry($apiUrl, $data) |
|
480 | |||
481 | //token 刷新后重试 get |
||
482 | View Code Duplication | public static function get_retry($apiUrl) |
|
526 | |||
527 | /** |
||
528 | * 对接口返回的数据进行验证和组装. |
||
529 | * |
||
530 | * @author Tian |
||
531 | * |
||
532 | * @date 2015-12-08 |
||
533 | * |
||
534 | * @param array $apiReturnData 由_post|| _get方法返回的数据. |
||
535 | * |
||
536 | * @return array|bool |
||
537 | */ |
||
538 | View Code Duplication | public static function packData($apiReturnData) |
|
608 | |||
609 | /** |
||
610 | * 接口加密方法. |
||
611 | * |
||
612 | * @param string $data 要加密的字符串 |
||
613 | * @param string $key 加密密钥 |
||
614 | * @param int $expire 过期时间 单位 秒 |
||
615 | * |
||
616 | * @return string |
||
617 | */ |
||
618 | View Code Duplication | public static function encrypt($data, $key, $expire = 0) |
|
642 | |||
643 | /** |
||
644 | * 解析头信息 |
||
645 | * |
||
646 | * @param $raw_headers |
||
647 | * |
||
648 | * @return array |
||
649 | */ |
||
650 | View Code Duplication | public static function http_parse_headers($raw_headers) |
|
689 | |||
690 | /** |
||
691 | * 缓存方法 |
||
692 | * |
||
693 | * @param string $name 缓存名 |
||
694 | * @param string $value 缓存值 如果不输入值 则根据缓存名返回缓存值. |
||
695 | * @param int $expires 缓存过期时间 默认0 即永不超时. 单位秒 |
||
696 | * |
||
697 | * @return bool|null|string |
||
698 | */ |
||
699 | View Code Duplication | public static function cache($name, $value = '', $expires = 0) |
|
728 | } |
||
729 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.