一个基于 PHP 构建的轻量级 MVC 框架,使用现代 PHP 开发实践,支持 RESTful API 和传统 Web 开发。
- 现代 PHP 架构:基于 PSR-4 自动加载,支持命名空间
- 灵活路由系统:使用
nikic/fast-route实现高性能路由 - MVC 架构:清晰的模型-视图-控制器分离
- RESTful API:支持 JSON API 和传统 Web 页面双模式
- 组件化设计:内置缓存、日志、数据库等核心组件
- 中间件支持:CORS、认证等中间件支持
- 用户认证:JWT Token 和 Session 双重认证机制
- 数据库抽象:使用
catfan/medoo轻量级数据库操作 - Bot 管理系统:集成 Bot 事件处理和管理功能
- PHP >= 7.4
- MySQL/MariaDB 5.7+
- Composer
- Web 服务器 (Apache/Nginx)
git clone [https://github.com/zskj/mvcYunhuBot.git](https://github.com/zskj/mvcYunhuBot.git)
cd mvcYunhuBotcomposer install编辑 app/config/web.php 文件中的数据库配置:
'db' => function() {
return new \Medoo\Medoo([
'type' => 'mysql',
'database' => 'your_database_name',
'host' => 'localhost',
'username' => 'your_username',
'password' => 'your_password',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_general_ci',
'port' => 3306,
'prefix' => '',
]);
},CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`auth_key` varchar(32) NOT NULL,
`password_hash` varchar(255) NOT NULL,
`password_reset_token` varchar(255) DEFAULT NULL,
`email` varchar(255) NOT NULL,
`status` smallint(6) NOT NULL DEFAULT 10,
`created_at` int(11) NOT NULL,
`updated_at` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;CREATE TABLE IF NOT EXISTS `event_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`bot_id` char(100) DEFAULT '',
`log` text,
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_bot_id` (`bot_id`),
KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;在 public/.htaccess 文件中添加:
RewriteEngine On
# Handle Angular and other front-end framework routes
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]server {
listen 80;
server_name your-domain.com;
root /path/to/your/project/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}mkdir -p runtime/logs
mkdir -p runtime/cache
chmod 755 runtime
chmod 755 runtime/logs
chmod 755 runtime/cachemvc/
├── app/ # 应用核心代码
│ ├── components/ # 自定义组件
│ ├── config/ # 配置文件
│ ├── controllers/ # 控制器
│ │ ├── api/v1/ # API v1 控制器
│ │ └── web/ # Web 页面控制器
│ ├── core/ # 核心组件
│ ├── helpers/ # 辅助函数
│ ├── middlewares/ # 中间件
│ ├── models/ # 数据模型
│ ├── services/ # 业务服务
│ └── views/ # 视图模板
├── public/ # Web 根目录
│ └── index.php # 入口文件
├── runtime/ # 运行时文件
│ ├── cache/ # 缓存文件
│ └── logs/ # 日志文件
└── composer.json # Composer 配置
路由在 app/config/web.php 的 routes 数组中定义:
'routes' => [
// API 路由
['GET', '/api/v1/users', ['api.v1:user/index']],
['POST', '/api/v1/users', ['api.v1:user/create']],
['GET', '/api/v1/users/{id:\d+}', ['api.v1:user/view']],
// Web 路由
['GET', '/login', ['web:auth/login']],
['POST', '/login', ['web:auth/login']],
['GET', '/', ['web:site/index']],
],<?php
namespace App\controllers\api\v1;
use App\controllers\api\ApiBaseController;
use App\models\User;
class UserController extends ApiBaseController
{
public function actionIndex()
{
$users = User::findAll();
return $this->asJson(['users' => $users]);
}
public function actionCreate()
{
$data = $this->getRequestData();
$userId = User::create($data);
if ($userId) {
return $this->asJson(['id' => $userId], 201);
}
return $this->asJson(['error' => 'Failed to create user'], 400);
}
}<?php
namespace App\controllers\web;
use App\controllers\web\WebBaseController;
use App\models\User;
class UserController extends WebBaseController
{
public function actionIndex()
{
$users = User::findAll();
return $this->render('user/index', ['users' => $users]);
}
}<?php
namespace App\models;
class User
{
private static $tableName = 'user';
public static function findAll()
{
$db = \App\helpers\db();
return $db->select(self::$tableName, '*');
}
public static function create($data)
{
$db = \App\helpers\db();
$data['password_hash'] = password_hash($data['password'], PASSWORD_DEFAULT);
$data['created_at'] = time();
$result = $db->insert(self::$tableName, $data);
return $result->rowCount() > 0 ? $db->id() : false;
}
}框架支持两种认证方式:
# 登录获取 Token
curl -X POST http://your-domain.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"password"}'
# 使用 Token 访问受保护的 API
curl -X GET http://your-domain.com/api/v1/auth/me \
-H "Authorization: Bearer YOUR_JWT_TOKEN"Web 页面使用传统的 PHP Session 进行认证,登录后自动维护登录状态。
| 方法 | 端点 | 描述 |
|---|---|---|
| POST | /api/v1/auth/login |
用户登录 |
| POST | /api/v1/auth/register |
用户注册 |
| GET | /api/v1/auth/me |
获取当前用户信息 |
| POST | /api/v1/auth/change-password |
修改密码 |
| 方法 | 端点 | 描述 |
|---|---|---|
| GET | /api/v1/users |
获取用户列表 |
| POST | /api/v1/users |
创建用户 |
| GET | /api/v1/users/{id} |
获取用户详情 |
| PUT | /api/v1/users/{id} |
更新用户 |
| DELETE | /api/v1/users/{id} |
删除用户 |
详细的 API 文档请参考 docs/README.md
本框架集成了强大的 Bot SDK,支持云湖机器人平台的各种功能。
重要: 使用前请先阅读 云湖开放平台官方文档 了解基础概念。
- 多种消息类型:文本、图片、视频、音频、文件等
- 事件处理:支持消息接收、用户关注、群组事件等
- 批量操作:支持批量发送消息
- 流式消息:支持实时流式发送
- 消息管理:支持消息编辑、撤回、查询
- 文件处理:支持文件上传和媒体处理
- 事件日志:自动记录所有 webhook 事件
use App\library\Bot;
// 配置参数
$token = 'your_bot_token'; // 云湖控制台获取的 Token
$botId = 'your_bot_id'; // 机器人云湖 ID
$config = [
'base_uri' => 'https://chat-go.jwzhd.com/open-apis/v1/',
'timeout' => 30,
'debug_mode' => false
];
// 创建 Bot 实例
$bot = new Bot($token, $botId, $config);// 发送文本消息
$response = $bot->send(
'user_id_or_group_id', // 接收者 ID
Bot::RECV_TYPE_USER, // 接收者类型(用户/群组)
Bot::CONTENT_TEXT, // 消息类型
'Hello, World!' // 消息内容
);
// 发送图片消息
$response = $bot->send(
'user_id',
Bot::RECV_TYPE_USER,
Bot::CONTENT_IMAGE,
'https://example.com/image.jpg' // 图片 URL
);
// 发送带按钮的消息
$buttons = [
[
'text' => '确认',
'actionType' => 'callback',
'actionData' => 'confirm_action'
],
[
'text' => '取消',
'actionType' => 'callback',
'actionData' => 'cancel_action'
]
];
$response = $bot->send(
'user_id',
Bot::RECV_TYPE_USER,
Bot::CONTENT_TEXT,
'请选择操作:',
$buttons
);// 批量发送给多个用户
$userIds = ['user1', 'user2', 'user3'];
$response = $bot->batchSend(
$userIds,
Bot::RECV_TYPE_USER,
Bot::CONTENT_TEXT,
'群发消息内容'
);// 流式发送文本消息
$messages = ['第一条消息', '第二条消息', '第三条消息'];
$response = $bot->sendStreamText(
'user_id',
Bot::RECV_TYPE_USER,
$messages,
1000 // 每条消息间隔 1 秒
);// 编辑消息
$response = $bot->edit(
'message_id', // 要编辑的消息 ID
'user_id', // 接收者 ID
Bot::RECV_TYPE_USER, // 接收者类型
Bot::CONTENT_TEXT, // 消息类型
'修改后的消息内容' // 新的消息内容
);
// 撤回消息
$response = $bot->recall(
'message_id', // 消息 ID
'chat_id', // 聊天 ID
Bot::CHAT_TYPE_BOT // 聊天类型
);
// 获取消息列表
$response = $bot->getMessages(
'chat_id', // 聊天 ID
Bot::CHAT_TYPE_BOT, // 聊天类型
null, // 消息 ID(可选)
10, // 之前的消息数量
10 // 之后的消息数量
);// 在控制器中处理 webhook
use App\controllers\api\v1\BotController;
use App\models\EventLog;
use App\library\Bot;
use App\components\OneEventHandler;
class BotController extends ApiBaseController
{
public function actionNotifyOne()
{
$token = 'your_bot_token';
$botId = 'your_bot_id';
$config = [
'base_uri' => 'https://chat-go.jwzhd.com/open-apis/v1/',
'timeout' => 30,
];
// 创建 Bot 实例
$bot = new Bot($token, $botId, $config);
// 获取 webhook 数据
$rawJson = $this->getApp()->request->getRawBody();
// 记录事件日志
$logId = EventLog::create([
'bot_id' => $botId,
'log' => $rawJson
]);
// 处理事件
$eventHandler = new OneEventHandler($bot);
$result = $eventHandler->handle($rawJson);
return $this->success($result, 'Event processed successfully');
}
}use App\library\BotEventHandler;
use App\library\Bot;
class CustomEventHandler extends BotEventHandler
{
// 处理普通消息
protected function onNormalMessage(array $event): array
{
$senderId = $event['data']['senderId'];
$content = $event['data']['content'];
// 自动回复
$this->bot->send(
$senderId,
Bot::RECV_TYPE_USER,
Bot::CONTENT_TEXT,
"您发送了:{$content}"
);
return ['code' => 0, 'message' => 'success'];
}
// 处理指令消息
protected function onInstructionMessage(array $event): array
{
$senderId = $event['data']['senderId'];
$content = $event['data']['content'];
// 处理不同指令
switch ($content) {
case '/help':
$response = '可用指令:\n/help - 显示帮助\n/time - 显示时间';
break;
case '/time':
$response = '当前时间:' . date('Y-m-d H:i:s');
break;
default:
$response = '未知指令,请输入 /help 查看帮助';
}
$this->bot->send(
$senderId,
Bot::RECV_TYPE_USER,
Bot::CONTENT_TEXT,
$response
);
return ['code' => 0, 'message' => 'success'];
}
// 处理用户关注事件
protected function onFollowed(array $event): array
{
$senderId = $event['data']['senderId'];
$welcomeMessage = '欢迎关注我们的机器人!\n输入 /help 查看可用功能。';
$this->bot->send(
C2FE
$senderId,
Bot::RECV_TYPE_USER,
Bot::CONTENT_TEXT,
$welcomeMessage
);
return ['code' => 0, 'message' => 'success'];
}
// 处理按钮点击事件
protected function onButtonClick(array $event): array
{
$senderId = $event['data']['senderId'];
$actionData = $event['data']['actionData'];
switch ($actionData) {
case 'confirm_action':
$response = '您点击了确认按钮';
break;
case 'cancel_action':
$response = '您点击了取消按钮';
break;
default:
$response = '未知按钮操作';
}
$this->bot->send(
$senderId,
Bot::RECV_TYPE_USER,
Bot::CONTENT_TEXT,
$response
);
return ['code' => 0, 'message' => 'success'];
}
}Bot::EVENT_MESSAGE_NORMAL // 普通消息事件
Bot::EVENT_MESSAGE_INSTRUCTION // 指令消息事件
Bot::EVENT_BOT_FOLLOWED // 机器人被关注
Bot::EVENT_BOT_UNFOLLOWED // 机器人被取消关注
Bot::EVENT_GROUP_JOIN // 加入群组
Bot::EVENT_GROUP_LEAVE // 离开群组
Bot::EVENT_BUTTON_INLINE // 按钮点击事件
Bot::EVENT_SHORTCUT_MENU // 快捷菜单事件
Bot::EVENT_BOT_SETTING // 机器人设置变更Bot::CONTENT_TEXT // 文本消息
Bot::CONTENT_IMAGE // 图片消息
Bot::CONTENT_FILE // 文件消息
Bot::CONTENT_VIDEO // 视频消息
Bot::CONTENT_AUDIO // 音频消息
Bot::CONTENT_HTML // HTML 消息
Bot::CONTENT_EXPRESSION // 表情消息
Bot::CONTENT_POST // 帖子消息
Bot::CONTENT_FORM // 表单消息Bot::RECV_TYPE_USER // 用户
Bot::RECV_TYPE_GROUP // 群组Bot::CHAT_TYPE_BOT // 机器人聊天
Bot::CHAT_TYPE_GROUP // 群组聊天use App\models\EventLog;
// 查询特定机器人的日志
$logs = EventLog::findByBotId('bot_id', 1, 20);
// 查询所有日志
$allLogs = EventLog::findAll(1, 50);
// 根据 ID 查询日志
$log = EventLog::findById(123);在 app/config/web.php 中可以配置 Bot 管理器:
'botManager' => [
'class' => 'App\\core\\BotManager',
'config' => [
'base_uri' => 'https://chat-go.jwzhd.com/open-apis/v1/',
'timeout' => 30,
'debug_mode' => false,
'max_image_size' => 10 * 1024 * 1024, // 10MB
'max_video_size' => 20 * 1024 * 1024, // 20MB
'max_file_size' => 20 * 1024 * 1024, // 20MB
]
],Bot SDK 会自动处理 API 错误并返回标准格式的响应:
$response = $bot->send(...);
if ($response['code'] === 0) {
// 发送成功
echo "消息发送成功,消息 ID: " . $response['data']['msgId'];
} else {
// 发送失败
echo "发送失败: " . $response['message'];
}开启调试模式可以查看详细的 API 调用信息:
$config = [
'debug_mode' => true,
'log_file' => '/path/to/bot.log'
];
$bot = new Bot($token, $botId, $config);# 创建管理员用户
curl -X POST http://localhost/api/v1/users \
-H "Content-Type: application/json" \
-d '{
"username": "admin",
"email": "admin@example.com",
"password": "admin123",
"status": 10
}'
# 创建普通用户
curl -X POST http://localhost/api/v1/users \
-H "Content-Type: application/json" \
-d '{
"username": "user1",
"email": "user1@example.com",
"password": "user123",
"status": 10
}'在 public/index.php 中设置开发模式:
defined('MVC_DEBUG') or define('MVC_DEBUG', true);
defined('MVC_ENV') or define('MVC_ENV', 'dev');框架会自动记录错误日志到 runtime/logs/ 目录:
// 使用日志组件
$logger = \App\helpers\logger();
$logger->info('用户登录', ['user_id' => 123]);
$logger->error('数据库连接失败', ['error' => $e->getMessage()]);本说明文档和部分代码由AI 编写
感谢使用轻量级 PHP MVC 框架! 🎉