# MengPHP **Repository Path**: MisterTiger/meng-php ## Basic Information - **Project Name**: MengPHP - **Description**: 模块化小型PHP框架 - **Primary Language**: PHP - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2023-04-25 - **Last Updated**: 2023-04-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MengPHP - 模块化, 静态化, 层级少, 易调试, 支持多数据库链接/读写分离 - 参考文档: http://doc.hearu.top/ - 如果不需要连接数据库或Redis可以不配置 ## 目录结构 ``` MengPHP Framework |-- core 框架的核心类 |-- config 配置文件 |-- libs 第三方库 |-- model 模型类, 理论上用于写获取数据的具体逻辑, 只放置在根目录下, 任何控制器都可以调用到 |-- db 表结构信息, 自动从数据库读取表结构信息生成的类文件, 方便SQL组装和了解表结构 |-- router 路由规则文件 |-- modules 项目模块 |-- view 视图文件 |-- tool 框架自带的登录注册模块的SQL,数据库配置文件样例,windows启动php-cgi的脚本 |-- update 框架自更新脚本 |-- static 静态文件存放 |-- cli.php 命令行下的入口文件 php cli.php -q m_c_a `-- index.php 入口文件 ``` ## 安装步骤 1. 下载框架代码到 `E:/php/code/project` 2. 配置NGINX ```` server { listen 80; server_name www.test.com; location ~ \.ico|jpg|gif|png|js|css$ { root E:/php/code/project/static; #expires 1h; } location / { root E:/php/code/project; fastcgi_pass 127.0.0.1:9720; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root/index.php; include fastcgi_params; } } ```` 3. 修改hosts文件,添加解析:`127.0.0.1 www.test.com` 4. 启动nginx; 5. 启动php: php-cgi.exe(windows) 或 php-fpm (Linux) 6. 在浏览器中输入 www.test.com 访问首页 > 注: php和nginx在windows上的启动代码可以参考 `tool/script/` 目录下的启动脚本 ## 核心功能使用说明 ### URL路由 > 核心代码参考 core/Route.php::matchURI(); #### 配置路由规则 - 所有对外可访问的接口都要在 router/*.php 中配置映射规则, 接口与真正的方法是映射关系, 不直接暴露源代码的方法名 - 路由规则分散在多个文件中, 防止多人协作开发时代码冲突 ##### 举例 > router/test.php ``` $test = [ 'article_list_(\d+)' => 'article/home/get_list/page/$1', 'detail_(\d{3})' => 'article/index/detail/id/$1', ]; ``` #### 路由种类 ##### 1.默认路由: > 如果浏览器中只输入域名, 没有URI,框架会默认找到 `modules/index/index.php::index()` 方法并执行 ``` http://www.test.com/ ``` ##### 2.正则路由 ###### 指定路由文件(推荐) > 好处是简化路由规则的编写, 跟其他模块的路由规则隔离, 防止重复 ``` http://www.test.com/test/detail_123 //这里会直接去找 router/test.php 里边的规则进行匹配 ``` ###### 不指定路由文件 > 这种情况(不写 `test/`), 会陆续读取 router/*.php 文件, 每读取一个文件就进行匹配, 直到匹配成功 ``` http://www.test.com/detail_123 ``` > 注: 也可以通过执行命令 `php cli.php -q router_cache` 来合并所有的配置文件, 提高匹配效率 #### 在命令行中使用 > 两种写法: ``` php cli.php -q cli/db_class //指定去匹配router/cli.php中的路由 php cli.php -q db_class //从所有规则中去找 ``` ### 获取请求数据 > 参考 core/Request.php (数据校验的配置在config/VerifyConfig.php) 1. 获取一个值 ``` Request::Get('a', 'default'); Request::Post('a'); Request::Cookie('a'); Request::Route('a'); ``` 2. 按类型获取 ``` Request::setGet()::Number('age', 11); Request::setPost()::Int('age', 11); Request::setCookie()::Float('age', 1.11); Request::setServer()::String('name', 'zs'); ``` 3. 一次获取多个值, 没有则用默认值替代 ``` Request::setPost()::pickData(['a' => 0, 'b' => '', 'c' => '0']); ``` ### 返回结果 > 参考 core/Response.php 1. 输出固定格式的json数据 ``` $a = ['list' => [1,2,3,4]]; Response::json(10000, '用户列表', $a); 结果: {"code":10000,"msg":"\u7528\u6237\u5217\u8868","data":{"list":[1,2,3,4]}} ``` 2. 便捷调用 > Response::json()的简写, 返回结构是一样的 ``` //成功返回: Response::success($a); Response::success($a, '用户列表'); Response::success($a, '用户列表', 20000); ``` ``` //失败返回: Response::error('参数错误'); 结果: {"code":"-1","msg":"\u53c2\u6570\u9519\u8bef","data":[]]} Response::error('参数错误', $a); 结果: {"code":"-1","msg":"\u53c2\u6570\u9519\u8bef","data":{"list":[1,2,3,4]},"url":""} Response::error('参数错误', $a, 20001); 结果: {"code":2001,"msg":"\u53c2\u6570\u9519\u8bef","data":{"list":[1,2,3,4]}} ``` 3. 返回任意结构的json数据 ``` Response::jsonReturn($a); //{"list":[1,2,3,4]} ``` 4. 跳转 ``` Response::notify('页面找不到啦~'); //页面找不到啦~ Response::redirect('充值成功, 页面即将跳转', 'http://www.hearu.top', 3); Response::jump('http://www.hearu.top'); //直接跳转 ``` ### 返回HTML页面 > 参考: core/View.php 1. 显示单个页面 ``` View::display(); ``` 2. 插入式显示页面(一个HTML页面框架, 里边有占位符:{{xxx}}) ``` View::render(); ``` ### 数据库操作 > 更多增删改查操作请查看在线文档 #### 数据库连接配置 1. 准备数据库的: 主机名/用户名/密码/端口/字符集等 2. 生成json文件, 放置到某个可以访问到的目录下边 ``` { "default":{ "write":[ {"host":"127.0.0.1", "username":"root", "password":"", "port":3306, "charset":"utf8mb4"} ], "read":[ {"host":"127.0.0.1", "username":"root", "password":"", "port":3306, "charset":"utf8mb4"} ] }, "other":{ "write":[], "read":[] } } ``` 3. 更改cli.php 和 index.php 的宏定义 ``` define('MYSQL_HOST_FILE', 'D:/server/code/dbConfig.json'); ``` #### 数据库连接方法 1. 虚拟表名连接 ``` Model::link(vhost); //其中 vhost 是真实表名的别名, 在 config/virtual_table.php中配置 ``` 2. 真实表名连接 ``` use DB\defaults\user; Model::table(user::$user); //其中的 user 是 db/defaults/user.php 的文件名, 此文件可以通过工具创建 ``` #### 数据库查询 > 两种方法除了连接方法不一样外, 没有其他区别 1. 虚拟表名连接法 ``` $rs = Test::link('note') ->fields('id,content') ->where(['uid' => 1, 'age' => 20]) ->whereOp('id', '>', 1) ->whereIn('status', [0,1,2]) ->order('id desc') ->limit(10) ->selectAll(); var_dump($rs, Test::$currentSql); ``` 2. 真实表名连接法 ``` use DB\defaults\test\user; $rs = DB::table(user::$user) ->where(['status' => 0]) ->whereOp('uid', '<', 10) ->order('uid desc') ->selectAll(); Response::success([$rs,user::$default]); ``` #### 利用工具自动生成表信息文件 > 需要先配置好数据库连接 (生成内容比较简单, 可根据自己项目的需要更改 modules/cli/db.php 中的代码) 1. 进入代码根目录执行下边命令: ``` php cli.php -q cli/db_cache ``` 2. 此命令会为每个表生成一个类文件(生成内容参考 db/defaults/user.php), 类中有: - 主机名 - 数据库名 - 真实表名 - 主键索引字段名 - 每个字段的详细信息(其实也不太详细, 可以自己改改) ### 文件日志 > 参考 libs/FileLog.php
> 日志文件存放的目录在入口文件 index.php 和 cli.php 中配置: LOGPATH 1. 常用 ``` FileLog::info([xxx], 'tag'); //日志文件: LOGPATH/info/yyyy-mm-dd.log, 数组内容会被转为json 或 FileLog::error('哈哈哈哈'); ``` 2. 设置日志跟踪ID ``` FileLog::$uuid = time().Fun::randChar(5); ``` ### Redis消息队列 - 基础类在: libs/IRedis.php - 队列类在: model/RedisQueue.php - 队列名的配置在: config/topics.php - 具体实现参考: modules/cli/queue.php ### DB消息队列 - 队列类在: model/DBQueue.php - Topic的配置在: config/topics.php - 需要添加消费者的crontab (路由: cli_queue_db_consumer), 代码在 module/cli/queue_db.php ### 自带登录注册模块 - 用户信息用cookie加密存储 - 功能有: 登录/注册/退出, 其中注册提供图形验证码 ### 自带前端单页面应用(SPA)样例 - 按照上边说明安装好PHP运行环境 - 配置好数据库信息(dbConfig.json) - 浏览器访问首页,即是一个可查看个多主机/数据库/表/字段等信息的web应用 ### 安全建议 - 尽量用post: 绝大部分的xss攻击是通过