# QPHP **Repository Path**: distributed-storage_1/QPHP ## Basic Information - **Project Name**: QPHP - **Description**: 1. 自研的PHP的MVC框架 2. 使用简单,扩展灵活,整个项目很小 3. 支持多个数据库mysql,oracle 4. 缓存支持redis,memcached - **Primary Language**: PHP - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-08-29 - **Last Updated**: 2025-08-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # QPHP #### 计划: #### 1.C语言实现php连接池功能,php扩展形式 #### 2.php多线程的实现 #### 3.开发按需加载功能,如: ##### 3.1开启语言功能,核心才会加载语言的功能模块相关文件 ##### 3.2默认只加载 错误异常模块,MySQL模块,oracle模块,redis模块,memcache模块 ### 开发功能: ##### 1.qphp是一个轻量级的phpmvc框架 ##### 框架执行时间:6毫秒,thinkphp执行时间:19毫秒 ##### 2.支持mysql,oracle,memcache,redis ##### 3.jwt生成token,和验证 ##### 4.增加路由功能,跨域请求 ##### 5.新增命名空间namespace ##### 6.完成增删改查(CURD)功能 ##### 7.全局配置功能,模块配置功能 ##### 8.新增分库功能,多库切换操作,分表联查,连接有简单连接池管理 ##### 9.新增链式查询功能 ##### 10.路由实现跨域和分组 ##### 11.优化核心pdo组件链接mysql,oracle组件化配置,可插拔扩展(思想:高内聚,低耦合) ##### 12.memcache,redis加入框架核心,取消在模块中配置缓存 ##### 13.升级到php8.2.0验证器组件计划重写 ##### 14.新增验证器,修改验证器的设计方案,使其扩展简单 ##### 15.验证器支持多语言验证,中英文,支持验证和过滤功能 ##### 16.框架也支持多语言,中|英文|等等,全局配置APP_LANG=>TRUE ##### 17.jwt重写生成长短token,无刷新长token获取短token ##### 18.所有接口rsa数据加密解密,数据加签,加签后验证 ###### 1.前端所有接口,先加签名,在加密数据和签名 ###### 2.后端先解密数据,验证签名,然后接收数据 ###### 3.js前端rsa加密加签,后端解密,验签 ###### 加签解签 D:\phpstudy_pro\WWW\www.qphp.com\application\admin\Resource\jsrsasign11.1.0 ###### 加密解密 D:\phpstudy_pro\WWW\www.qphp.com\application\admin\Resource\jsencrypt3.3.2 ##### 19.nginx伪静态 ```php 快速配置: if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=/$1 last; break; } 完全配置: server { listen 80; server_name all.bjed.com; root "F:\www\asdata"; location / { index index.html index.htm index.php; #autoindex on; # 新增内容开始 if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=/$1 last; break; } # 新增内容结束 } } ``` ##### 20.美化异常和用户错误提示信息 ```php /** * 测试系统异常和自定义错误 * 系统异常优先抛出,系统异常解决后,才会抛出用户自定义错误信息 */ public function testError(){ //抛出用户自定义错误信息 trigger_error("错误信息", E_USER_ERROR); //系统异常优先抛出 $a; //$a } ``` ##### 21.新增中间件,只实现了前置后置功能 ```php middleware('admin\middleware\IndexMiddleware')->middleware('admin\middleware\UserMiddleware')->get('admin/testMiddleware','admin/index/testMiddleware')->header('Access-Control-Allow-Origin','*')->header('Access-Control-Allow-Credentials', 'true')->allowCrossDomain(); ; //分组1 Route::middleware('admin\middleware\UserMiddleware')->group('admin/',function(){ Route::get('age','admin/index/age'); // Route::get('name','admin/index/name'); Route::get('userAdd','admin/user/add'); Route::get('userEdit','admin/user/edit'); Route::get('userDel','admin/user/del'); })->header('Access-Control-Allow-Origin','*')->header('Access-Control-Allow-Credentials', 'true')->allowCrossDomain(); //分组2 Route::middleware('admin\middleware\LoginMiddleware')->group('admin1/',function(){ Route::get('name','admin/index/name'); })->header('Access-Control-Allow-Origin','*')->header('Access-Control-Allow-Credentials', 'true')->allowCrossDomain(); ``` ##### 9.全局配置功能,模块配置功能 ###### 9.1.模块配置会自动覆盖全局配置的参数的数据 ###### 9.2.跟业务无关的配置只会在全局配置文件生效如: ```php 'RPC_RUN'=>false,//是否开启rpc 'ROUTE_PATH'=>true,//是否开启路由模式 'APP_DEBUG'=> true,//debug//开启错误是否显示到页面 ``` ##### 10.生成分布式id ```php 安装: https://packagist.org/packages/dekuan/dedid composer require dekuan/dedid ``` ##### 11.新增分库功能,多库切换操作,连接有简单连接池管理 ```php array( 'host' => '127.0.0.1', 'dbname' => 'qphp', 'mysql_user' => 'qphp', 'mysql_pwd' => '123456', 'port' => 3306 ), 'mysql_1' => array( 'host' => '127.0.0.1', 'dbname' => 'qphp_01', 'mysql_user' => 'root', 'mysql_pwd' => '123456', 'port' => 3306 ), 'mysql_2' => array( 'host' => '127.0.0.1', 'dbname' => 'qphp_02', 'mysql_user' => 'root', 'mysql_pwd' => '123456', 'port' => 3306 ), ); ``` ```php php模型分表查询,并排序 =(select id from collect order by id limit 90000,1) limit 10; $data = []; //第二页 id<35 //分页由前端做,一次性返回多条数据 $sql1="select * from ((select * from q_user_01 )UNION ALL (select * from q_user_02)) as u where u.id<35 ORDER BY u.create_time desc limit 10"; $this->getLastSql(); $data_1 = $this->Db('mysql_1')->executeSql("getRows",$sql1); $sql2="select * from ((select * from q_user_01 )UNION ALL (select * from q_user_02)) as u where u.id<35 ORDER BY u.create_time desc limit 10"; $data_2=$this->Db('mysql_2')->executeSql("getRows",$sql2); $sql3="select * from ((select * from q_user_01 )UNION ALL (select * from q_user_02)) as u where u.id<35 ORDER BY u.create_time desc limit 10"; $data_3=$this->Db('mysql_3')->executeSql("getRows",$sql3); $data = array_merge($data_1,$data_2,$data_3); $sort_c = array_column($data,'create_time'); $sort_u = array_column($data,'updat_time'); array_multisort($sort_c, SORT_DESC,SORT_NUMERIC,$sort_u,SORT_DESC,SORT_NUMERIC,$data); return $data; } ``` ##### 10.生成分布式id # ALGORITHM ### Bit structure It's a 64 bits bigint. ~~~ 0 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx x xxxxx xxxxx xxxx xxxxxxxx ~~~ ### Details Position | Length | Usage | Remark ----------|----------|----------|---------- 0 | 1 | Reserved | Always be 0 1~41 | 41 | Escaped Time (in millisecond) | 0~69 years 42~46 | 5 | Number of data center | 0~31 47~51 | 5 | Number of data node in the data center | 0~31 52~63 | 12 | Random / Hash | 0~4095 # Bit marks ### Center ~~~ 0 00000000 00000000 00000000 00000000 00000000 0 11111 00000 0000 00000000 00000000 00000000 00000000 00000000 00000000 00111110 00000000 00000000 00 00 00 00 00 3E 00 00 ~~~ ### Node ~~~ 0 00000000 00000000 00000000 00000000 00000000 0 00000 11111 0000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 11110000 00000000 00 00 00 00 00 01 F0 00 ~~~ ### Escaped Time ~~~ 0 11111111 11111111 11111111 11111111 11111111 1 00000 00000 0000 00000000 01111111 11111111 11111111 11111111 11111111 11000000 00000000 00000000 7F FF FF FF FF C0 00 00 ~~~ ### Random or Hash value ~~~ 0 00000000 00000000 00000000 00000000 00000000 0 00000 00000 1111 11111111 00000000 00000000 00000000 00000000 00000000 00000000 00001111 11111111 00 00 00 00 00 00 0F FF ~~~ # HOW TO USE ### Create an new id normally ~~~ $cDId = CDId::getInstance(); $nCenter = 0; $nNode = 1; $arrD = []; $nNewId = $cDId->createId( $nCenter, $nNode, null, $arrD ); echo "new id = " . $nNewId . "\r\n"; print_r( $arrD ); ~~~ ##### output ~~~ new id = 114654484990270790 Array ( [center] => 0 [node] => 1 [time] => 27335759399 [rand] => 3398 ) ~~~ ### Create an new id with crc32 hash value by a specified string ~~~ $cDId = CDId::getInstance(); $nCenter = 0; $nNode = 15; $sSrc = "dekuan"; $arrD = []; $nNewId = $cDId->createId( $nCenter, $nNode, $sSrc, $arrD ); echo "new id = " . $nNewId . "\r\n"; print_r( $arrD ); ~~~ ##### output ~~~ new id = 114654631304370386 Array ( [center] => 0 [node] => 1 [time] => 27335794283 [rand] => 2258 ) ~~~ ### Parse an id for getting the details ~~~ $cDId = CDId::getInstance(); $arrId = $cDId->parseId( 114654631304370386 ); print_r( $arrId ); ~~~ ##### output ~~~ Array ( [center] => 0 [node] => 1 [time] => 27335794283 [rand] => 2258 ) ~~~ ### 1.下面是配置的一个案例全局配置,和模块admin,index的配置 ```php //全局配置文件加载在config\目录 config.php /** * 总配置文件 */ $config['app'] = array( 'RPC_RUN'=>false,//是否开启rpc 'ROUTE_PATH'=>true,//是否开启路由模式 'APP_DEBUG'=> true,//debug//开启错误是否显示到页面 //全局数据库配置 'mem' => array( 'host' => '127.0.0.1', 'port' => '11211' ), 'redis' => array( 'host' => '127.0.0.1', 'port' => '6379' ), ); //局部配置文件在application\admin\Config\目录 config.php array( 'host' => '127.0.0.1', 'dbname' => 'qphp', 'mysql_user' => 'qphp', 'mysql_pwd' => '123456', 'port' => 3306 ), 'mysql_1' => array( 'host' => '127.0.0.1', 'dbname' => 'qphp_01', 'mysql_user' => 'root', 'mysql_pwd' => '123456', 'port' => 3306 ), 'mysql_2' => array( 'host' => '127.0.0.1', 'dbname' => 'qphp_02', 'mysql_user' => 'root', 'mysql_pwd' => '123456', 'port' => 3306 ), ); //局部配置文件在application\index\Config\目录 config.php array( 'host' => '192.168.123.101', 'dbname' => 'QPHP', 'oracle_user' => 'QPHP', 'oracle_pwd' => '123456', 'port' => 1521 ), //全局数据库配置 'oracle_1' => array( 'host' => '192.168.123.101', 'dbname' => 'QPHP_01', 'oracle_user' => 'QPHP_01', 'oracle_pwd' => '123456', 'port' => 1521 ), ); ``` ### 1.新增Model的mysql链式查询 ```php //查询 public function getUsers(){ $data = $this->Db('mysql_0')->table('mm_user')->asTable('u') ->field('u.*,ui.birthday,ui.info,a.address_info,a.is_default') ->leftJoin('mm_user_info ui on ui.user_id = u.id') ->leftJoin('mm_address a on a.user_id =u.id') ->where() ->order('u.id desc') ->limit(0,10) ->select(); return $data; } public function getCount(){ $this->getLastSql(); $data_count = $this->Db('mysql_0')->table('mm_user')->asTable('u') ->field('u.*,ui.birthday,ui.info,a.address_info,a.is_default') ->leftJoin('mm_user_info ui on ui.user_id = u.id') ->leftJoin('mm_address a on a.user_id =u.id') ->where() ->count(); return $data_count; } //插入 $model = new UserModel(); $data =array( 'username'=>$username, 'age'=>$age, 'pwd'=>$password, 'address'=>$address ); $last_id = $model->Db('mysql_0')->table('mm_user')->insert($data); //修改 $model = new UserModel(); $arr =array( 'username'=>$username, 'age'=>$age, 'pwd'=>$pwd, 'address'=>$address ); $where =" id={$id}"; $res=$model->Db('mysql_0')->table('mm_user')->where($where)->update($arr); //删除 $model = new UserModel(); $where ="id={$id}"; $res= $model->Db('mysql_0')->table('mm_user')->where($where)->delete(); ``` ### 2.新增Model的oracle链式查询 ```php //查询 public function getUser(){ $data = $this->Db("oracle_0")->table('"mm_user"')->asTable('u') ->field('u.*,ui."birthday",ui."info",a."address_info",a."is_default"') ->leftJoin('"mm_user_info" ui on ui."user_id" = u."id"') ->leftJoin('"mm_address" a on a."user_id" =u."id"') ->where() ->order('u."id" desc') ->limit(0,2) ->select(); return $data; } public function getCount(){ $data_count = $this->Db("oracle_0")->table('"mm_user"')->asTable('u') ->field('u.*,ui."birthday",ui."info",a."address_info",a."is_default"') ->leftJoin('"mm_user_info" ui on ui."user_id" = u."id"') ->leftJoin('"mm_address" a on a."user_id" =u."id"') ->where() ->count(); return $data_count; } //插入 $model = new UserModel(); $data =array( 'id'=>112, 'username'=>$username, 'age'=>$age, 'pwd'=>$password, 'address'=>$address ); $last_id = $model->Db('mysql_0')->table('"mm_user"')->insert($data); //修改 $model = new UserModel(); $arr =array( 'username'=>$username, 'age'=>$age, 'pwd'=>$pwd, 'address'=>$address ); $where ="\"id\"={$id}"; $res=$model->Db('mysql_0')->table('"mm_user"')->where($where)->update($arr); //删除 $model = new UserModel(); $where ="\"id\"={$id}"; $res= $model->Db('mysql_0')->table('"mm_user"')->where($where)->delete(); ``` ### 3.新增验证器过滤器 ###### composer require inhere/php-validate:dev-master ###### 地址:https://packagist.org/packages/inhere/php-validate ##### 方式2: 继承类 Validation 创建一个新的class,并继承 Inhere\Validate\Validation。用于一个(或一系列相关)请求的验证, 相当于 laravel 的 表单请求验证 此方式是最为完整的使用方式,可以配置规则,设置字段翻译,设置自定义的错误消息等 ```php use Inhere\Validate\Validation; class CommonValidate extends Validation { # 进行验证前处理,返回false则停止验证,但没有错误信息,可以在逻辑中调用 addError 增加错误信息 public function beforeValidate(): bool { return true; } # 进行验证后处理,该干啥干啥 public function afterValidate(): bool { return true; } } class UserValidate extends CommonValidate { public function rules(): array { return [ // 字段必须存在且不能为空 ['tagId,title,userId,freeTime', 'required'], // 4<= tagId <=567 ['tagId', 'size', 'min'=>4, 'max'=>567, 'filter' => 'int'], // title length >= 40. 注意只需一个参数的验证,无需加 key, 如这里的 40 ['title', 'min', 40, 'filter' => 'trim'], // 大于 0 ['freeTime', 'number'], // 含有前置条件 ['tagId', 'number', 'when' => function($data) { return isset($data['status']) && $data['status'] > 2; }], // 在验证前会先过滤转换为 int。并且仅会在指明场景名为 'scene1' 时规则有效 ['userId', 'number', 'on' => 'scene1', 'filter' => 'int'], ['username', 'string', 'on' => 'scene2', 'filter' => 'trim'], // 使用自定义正则表达式 ['username', 'regexp' ,'/^[a-z]\w{2,12}$/'], // 自定义验证器,并指定当前规则的消息 ['title', 'custom', 'msg' => '{attr} error msg!' ], // 直接使用闭包验证 ['status', function($status) { if (is_int($status) && $status > 3) { return true; } return false; }], // 标记字段是安全可靠的 无需验证 ['createdAt, updatedAt', 'safe'], ]; } // 定义不同场景需要验证的字段。 // 功能跟规则里的 'on' 类似,两者尽量不要同时使用,以免混淆。 public function scenarios(): array { return [ 'create' => ['user', 'pwd', 'code'], 'update' => ['user', 'pwd'], ]; } // 定义字段翻译 public function translates(): array { return [ 'userId' => '用户Id', ]; } // 自定义验证器的提示消息, 默认消息请看 {@see ErrorMessageTrait::$messages} public function messages(): array { return [ // 使用验证器名字指定消息 'required' => '{attr} 是必填项。', // 可以直接针对字段的某个规则进行消息定义 'title.required' => 'O, 标题是必填项。are you known?', ]; } // 添加一个验证器。必须返回一个布尔值标明验证失败或成功 protected function customValidator($title): bool { // some logic ... // $this->getRaw('field'); 访问 data 数据 return true; // Or false; } } ``` ##### 使用 ```php // 验证 POST 数据 $v = UserValidate::check($_POST); // 验证失败 if ($v->isFail()) { var_dump($v->getErrors()); var_dump($v->firstError()); } // 验证成功 ... $safeData = $v->getSafeData(); // 验证通过的安全数据 // $postData = $v->all(); // 原始数据 $db->save($safeData); ```