# MengPHP **Repository Path**: myDcool/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**: 4 - **Forks**: 1 - **Created**: 2022-04-28 - **Last Updated**: 2025-02-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MengPHP - 模块化, 静态化, 层级少, 易调试, 支持多数据库链接/读写分离 - 参考文档: http://doc.hearu.top/ (最近服务器被攻击, 可以到 /tool/document/ 目录下查看文档) - 如果不需要连接数据库或Redis可以不配置 ## 一, 目录结构 ``` MengPHP Framework |-- core 框架的核心类 |-- config 配置文件 |-- libs 第三方库 |-- model 模型类, 理论上用于写获取数据的具体逻辑, 只放置在根目录下, 任何控制器都可以调用到 |-- tables 表结构信息, 自动从数据库读取表结构信息生成的类文件, 方便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 ``` # 精简版 (没有限速和安全配置) http { ... 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 unix:/run/php-fpm/www.sock; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root/index.php; include fastcgi_params; } } } ``` ``` # 增加限速和安全配置 http { ... # 限速全局配置, 详细用法可去nginx官网查询 (https://nginx.org/en/docs/ -> ngx_http_limit_req_module ngx_http_limit_conn_module) limit_rate 100k; # 每个链接限制 100k 字节 limit_req_zone $binary_remote_addr zone=perip:5m rate=1r/s; # 单IP请求限制, 每秒1个, 5M的记录空间, 空间名为perip, 下边会用到 limit_req_zone $server_name zone=perserver:5m rate=50r/s; # 单个server响应限制, 5M的记录空间, 空间名为perserver, 下边会用到 ... server { listen 80; server_name www.test.com; #限速配置 (也可以写在location中) limit_req zone=perip burst=5 nodelay; # 使用名为perip的限速设置, 超出的不再处理直接返回503 limit_req zone=perserver burst=10; # 使用名为perserver的限速设置, 超出的排队等待处理 #安全配置开始 if ($request_method !~ ^(GET|POST)$) {return 405;} location ~ x0 {return 404;} # 8进制/16进制数据限制 location ~ ^/\..*{return 404;} # 以.开始的访问限制(比如 .evn .git) location ~ \./.* {return 404;} # 路径访问限制 (比如: /../../abc.xxx) location ~* ^/http {return 404;} location ~* \.(php|asa|asp|aspx|html|git|sh|exe|xml|json)$ {return 404;} # 后缀限制 #安全配置结束 location ~ \.(ico|jpg|gif|png|js|css)$ { root E:/php/code/project/static; #expires 1h; } location / { root E:/php/code/project; # fastcgi_pass unix:/run/php-fpm/www.sock; 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 - windows: - 安装: 从官网下载最新的php代码, 解压到某个目录 - 启动: 参考`tool/script/` 目录下的启动脚本 - Linux - 安装 & 启动 & 开启自启: 使用remi源进行安装, 参考: https://www.cnblogs.com/iLoveMyD/p/17127099.html ### 6. 在浏览器中输入 www.test.com 访问首页 ## 三, 核心功能使用说明 ### URL路由 > 核心代码参考 core/Route.php::matchURI(); #### 1. 配置路由规则 - 所有对外可访问的接口都要在 router/*.php 中配置映射规则, 接口与真正的方法是映射关系, 不直接暴露源代码的方法名 - 路由规则分散在多个文件中, 防止多人协作开发时代码冲突 #### 2. 配置举例 ``` //router/test.php http://www.test.com/test/detail_123 $GLOBALS['router']['test'] = [ 'article_list_(\d+)' => 'article/home/get_list/page/$1', 'detail_(\d{3})' => 'article/index/detail/id/$1', ]; //router/user.php http://www.test.com/user/login $GLOBALS['router']['user'] = [ //用户账号相关 'default' => 'user/login', //都不匹配时走这个'default'路由 'user' => 'user/index', 'login' => 'user/login/index', 'register' => 'user/register/index', 'logout' => 'user/logout/index', ]; ``` #### 在命令行中使用路由 ``` php cli.php -q cli/db_class //指定去匹配router/cli.php中的路由 ``` ### 获取请求数据 > 参考 core/Request.php #### 1. 获取一个值 ``` Request::Get('a', 'default'); Request::Post('a'); Request::Cookie('a'); Request::Route('a'); Request::Json('a'); //前端以json形式上传的数据(content-type: application/json) ``` #### 2. 按类型获取 ``` Request::Get()::Number('age', 11); Request::Post()::Int('age', 11); Request::Cookie()::Float('age', 1.11); Request::Server()::String('name', 'zs'); ``` #### 3. 一次获取多个值, 没有则用默认值替代 ``` Request::Post()::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(); ``` ### 数据库 > 更多增删改查操作请查看在线文档 #### 数据库链接账号密码配置 ``` 入口文件 index.php 中有个define配置: define('MYSQL_HOST_FILE', '/var/www/dbConfig.json'); //存放mysql主机信息的json文件地址, 参考 tool/dbConfig.json 修改这个配置的值为dbConfig.json的实际位置即可 ``` #### 相关操作摘要 ``` use Tables\DefaultUser as User; //增 $insertId = User::user() ->insert(['username' => '王五', 'age' => 18]) ->insertId; //删 $affectRows = User::user() ->where(['uid' => 5]) ->delete() ->affectRows; //改 $affectRows = User::user() ->where(['uid' => 1]) ->updateVal(['age' => 20]) ->updateOp('a', 'a', '+', 1) ->updateOp('a', 'b', '+', 2) ->update() ->affectRows; //查 $rs = User::user() ->where(['status' => 0, 'deleted' => 0]) ->whereOp('uid', '<', 10) ->order('uid desc') ->selectAll(); //join $tbUser = User::$user; $tbUserRole = User::$role_bind; $tbRole = User::$role; $rs = User::user() ->joinFields($tbUser, 'uid,username') ->joinFields($tbRole, 'name,access') ->joinTable([$tbUser, 'uid'],[$tbUserRole, 'uid']) ->joinTable([$tbUserRole, 'roleid'], [$tbRole, 'id']) ->where(['status' => 0, 'is_logout' => 0], $tbUser) ->where(['status' => 0], $tbUserRole) ->where(['status' => 0], $tbRole) ->joinAll(); Response::success($rs, DB::$currentSql); ``` ### 文件日志 > 参考 libs/FileLog.php
> 日志文件存放的目录在入口文件 index.php 和 cli.php 中配置: `LOGPATH` #### 1. 常用 ``` FileLog::info([msg], 'tag'); //日志文件: LOGPATH/info/yyyy-mm-dd.log, 数组内容会被转为json, 字符串会原样输出 或 FileLog::error('哈哈哈哈'); ``` #### 2. 设置日志跟踪ID ``` FileLog::$trace_id = time().Fun::randChar(5); //默认为 uniqid() 或 $_GET['trace_id'] 的值 ``` ### 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攻击是通过