我欲乘风九万里
梦的起点
心灵之声
珊瑚礁
编码之舞
梦中的微风
项目编码
聚合登录文档
建议
AI助手
项目重构-thinkphp8.0
> 背景 > 公司的主营项目是CI,版本3.0;自从接触过这个CI项目,各种问题不断,没有完善的composer包机制,各种插件要么自己写,要么魔改别人的家的库,而且对编辑器支持非常的不友好,每次找个文件都很费劲。这个项目更牛的地方是,PHP版本由原来的7.3直接更新的8.1,听同事说php版本更新之后,项目都不能正常运行了,花了很长时间修改代码才得以使项目正常运行。但是为了网安等级,又到了升级php版本的时候了,前些天从8.1版本更新到8.3,项目代码又各种报错,即使最后更改到php8.2也不行。遂有了这次重构项目的计划,并且这此重构的任务落在我的身上。计划使用webman重写,我是非常的喜欢这个框架,什么websocket,多进程,定时器之类的写起来非常方便舒适,文档全性能也高,奈何公司觉得是个小众框架,以安全稳定为优先,最后选择thinkphp8. 一、安装框架 ```php composer create-project topthink/think tp ``` 二、安装基础类常用包 多应用安装 ```php composer require topthink/think-multi-app ``` http client ```php composer require guzzlehttp/guzzle ``` 接口文档 ```php composer require hg/apidoc ``` 三、创建多应用目录 四、编写中间件代码 ```php <?php declare (strict_types = 1); namespace app\api\middleware; use lib\exception\ApiException; use ReflectionClass; use think\facade\Log; use think\Request; class Api { /** * 统一处理请求中间件 * @var array */ private array $return = [ 'code' => 500, 'msg' => '', ]; public function handle(Request $request, \Closure $next) { $time = microtime(true); # 找到对应的控制器目录 $path = 'app\api\controller\\' . $request->controller(); try { $reflectionClass = new ReflectionClass($path); //反射 /* //规则验证,例如ip/域名 $this->isAllow($request); // 接口规则验签 $this->chenkSign($request); // token鉴权 $this->checkToken($request,$reflectionClass);*/ $reflectionMethod = $reflectionClass->getMethod($request->action()); // 获取方法的反射 $methodParameters = $reflectionMethod->getParameters(); // 获取方法的参数 // 处理参数 $paramsArray = []; foreach ($methodParameters as $parameter) { $paramName = $parameter->getName(); $paramValue = $request->param($paramName); $paramType = $parameter->getType()->getName(); if(in_array($paramType,['int','float']) && !is_numeric($paramValue)) { throw new ApiException('参数类型错误'.$paramType); } if($paramType==='string') { $paramValue = trim($paramValue); } if ($paramValue === null || $paramValue === '') { if (!$parameter->isDefaultValueAvailable()) { throw new ApiException('缺少必要参数: ' . $paramName); } else { $paramsArray[] = $parameter->getDefaultValue(); } } else { $paramsArray[] = $paramValue; } } } catch (\Exception $e) { $this->return['msg'] = $e->getMessage(); $this->return['path'] = $path.'\\'.$request->action(); $this->errorLog(); return json($this->return); } // 调用方法并传递参数 try { $res = $reflectionMethod->invokeArgs($reflectionClass->newInstance(), $paramsArray); $this->return['code'] = 200; $this->return['data'] = $res; } catch (ApiException $e) { $this->return['line'] = $e->getLine(); $this->return['msg'] = $e->getMessage(); $this->return['path'] = $path.'\\'.$request->action(); $this->errorLog(); } catch (\Exception $e) { // 处理异常,你可以将异常信息记录到日志或返回适当的错误响应 $this->return['file'] = $e->getFile(); $this->return['line'] = $e->getLine(); $this->return['msg'] = $e->getMessage(); $this->return['trace'] = $e->getTraceAsString(); $this->return['path'] = $path.'\\'.$request->action(); $this->errorLog(); } $this->return['ttl'] = microtime(true)-$time; return json($this->return); } /** * 验证规则 * @param Request $request * @return void */ public function isAllow(Request $request) { } /** * 验证签名 * @param Request $request * @return true * @throws ApiException */ public function chenkSign(Request $request) { $data = $request->all(); // 验证appid参数 if(empty($data['appid'])) throw new ApiException('缺少appid'); $config = config('appid'); if(empty($config[$data['appid']])) throw new ApiException('appid不存在'); $appSecret = $config[$data['appid']]; // 验证时间戳参数 if(empty($data['timestamp'])) throw new ApiException('缺少timestamp'); $time = time(); $startTime = $time-30; $endTime = $time+30; if($data['timestamp']<$startTime || $data['timestamp']>$endTime) throw new ApiException('timestamp错误'); // 验证随机字符串 if(empty($data['nonce_str'])) throw new ApiException('缺少nonce_str'); if(strlen($data['缺少nonce_str'])<8) throw new ApiException('nonce_str不符合规则'); if($data['nonce_str'] === cache($data['timestamp'])) throw new ApiException('nonce_str已使用'); cache($data['timestamp'],$data['nonce_str'],60); // 验签 if(empty($data['sign'])) throw new ApiException('sign'); $sign = $data['sign']; unset($data['sign']); $str = ''; ksort($data); foreach ($data as $k => $v) { if (is_array($v)) { $str .= $k . '=' . json_encode($v) . '&'; } elseif (is_bool($v)) { $str .= $k . '=' . ($v ? "true" : "false") . '&'; } elseif($v) { $str .= $k . '=' . $v . '&'; } } $sign2 = md5($str . $appSecret); if($sign !== $sign2) throw new ApiException('签名错误'); return true; } /** * 验证 token * @param Request $request * @param ReflectionClass $reflectionClass * @return true * @throws ApiException */ public function checkToken(Request $request,\ReflectionClass $reflectionClass) { $noCheck = $reflectionClass->getDefaultProperties()['noCheck'] ?? false; // 如果没有nocheck属性,则需要进行验证 $checkAction = $reflectionClass->getDefaultProperties()['checkAction'] ?? []; //需要验证的方法集合 if($noCheck && in_array($request->action(), $checkAction)) return true; $token = $request->header('Authorization'); if(empty($token)) throw new ApiException('缺少token'); return true; } /** * 记录响应失败的数据 * @param array $returnData 接口返回的响应数据 * @return void */ public function errorLog() { $data['return'] = $this->return; $data['path_info'] = request()->pathinfo(); $data['ip'] = request()->ip(); $data['request_time'] = date('Y-m-d H:i:s'); $data['params'] = request()->all(); Log::error(json_encode($data,320)); } } ``` 五、文档 1.制定了接口文档编写规则 2.制定了代码编写规则 3.待定 六、待定 2024-07-09 把基础的代码架构搭建起来,剩下搭建controller,logic,service,model层的架构 总结:一步一步走吧,目前只要求先搭建一个基础框架出来,后续的业务逻辑还需要确认是否往里面写。
ysian
我雾化科所
1
聚合登录之创建应用篇
2024-07-30
645
0
2
php函数之match
2024-07-29
582
0
3
聚合登录之常见问题
2024-07-30
489
0
4
聚合登录之前后端示例代码
2024-07-30
483
0
5
聚合登录之获取登录链接
2024-07-30
422
0
6
服务器瘦身
2023-11-01
413
5
7
centos下升级openssl
2023-11-30
413
0
8
我的第一篇博客
2023-09-28
402
0
9
supervisor的安装与使用
2023-11-02
383
0
10
editor.md 代码块没有下拉框
2023-10-06
352
2
PHP [9]
linux [4]
sh [1]
闲谈 [1]
css [2]
redis [2]
Cluster集群 [1]
git [1]
centos [1]
webman [2]
工具 [1]
OAuth2.0 [1]
项目 [1]
初始化 [1]
thinkphp [1]
Nginx [1]
往事 [1]
Mysql [1]
支付宝 [2]
抖音 [2]
qq [2]
聚合 [1]
登录 [1]
聚合登录 [4]
cache [1]
html [1]
queue [1]
Workerman版本
4.1.15
Webman版本
1.5.9
PHP版本
8.3.6
MYSQL版本
8.2.24
操作系统
CENTOS