# 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攻击是通过