20 KiB
20 KiB
ChatRoom 开发计划与注意事项
技术栈:Laravel 12 · PHP 8.4 · Laravel Reverb (WebSocket) · Redis · MySQL 8.0 · Laravel Horizon 原项目:
/Users/pllx/Web/chat/hp0709(VBScript ASP + MS Access 聊天室) 目标域名:http://chatroom.test(Herd 自动配置)
一、环境版本要求
| 组件 | 版本 |
|---|---|
| PHP | 8.4.5+ |
| Laravel Framework | v12.x |
| Laravel Reverb | latest(WebSocket 服务器) |
| Laravel Horizon | v5(Redis 队列可视化管理) |
| PHPUnit | v11(测试框架) |
| Node.js | 20.x LTS |
| MySQL | 8.0+ |
| Redis | 7.x |
二、代码规范(强制执行)
2.1 Laravel Pint 格式化
# 提交代码前必须运行,修复格式问题
vendor/bin/pint --dirty
# 检查格式问题(不修复)
vendor/bin/pint --test
# 格式化整个项目
vendor/bin/pint
2.2 PHP 8.4 类型系统(必须遵守)
// ✅ 正确:构造函数属性提升 (Constructor Property Promotion)
class ChatController extends Controller
{
public function __construct(
private readonly ChatStateService $chatState,
private readonly MessageFilterService $filter,
) {}
}
// ❌ 错误:不允许无参空构造函数
class SomeClass
{
public function __construct() {} // 禁止!
}
// ✅ 正确:显式返回类型 + 参数类型提示
public function send(SendMessageRequest $request): JsonResponse
{
// ...
}
// ✅ 正确:使用 PHP 8.4 新特性
// 联合类型
public function findUser(int|string $id): User|null {}
// readonly 属性
class MessageDto
{
public function __construct(
public readonly string $content,
public readonly string $fromUser,
public readonly int $roomId,
) {}
}
2.3 Laravel 12 中间件配置(重要)
Important
Laravel 12 已废弃
Kernel.php,中间件在bootstrap/app.php中配置。
// bootstrap/app.php
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php', // API 路由
channels: __DIR__.'/../routes/channels.php', // WebSocket 频道
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware): void {
// 注册聊天室登录验证中间件
$middleware->alias([
'chat.auth' => \App\Http\Middleware\ChatAuthenticate::class,
'chat.level' => \App\Http\Middleware\LevelRequired::class,
]);
// Session 中间件(Web 路由自动携带)
$middleware->web(append: [
\App\Http\Middleware\HandleInertiaRequests::class,
]);
})
->withExceptions(function (Exceptions $exceptions): void {
//
})->create();
2.4 中文注释规范(每个文件必须)
<?php
/**
* 文件功能:[本文件的业务职责描述]
*
* 对应原 ASP 文件:[原文件名.asp]
*
* @package App\[命名空间]
* @author ChatRoom Laravel
* @version 1.0.0
*/
namespace App\Services;
class ChatStateService
{
/**
* 用户进入聊天房间,将其信息写入 Redis。
*
* 替代原 ASP 的 Application("_user_list") 字符串拼接操作。
*
* @param int $roomId 房间 ID
* @param string $username 用户名
* @param array $userInfo 用户信息(等级、头像、性别等)
*/
public function userJoin(int $roomId, string $username, array $userInfo): void
{
// 将用户信息序列化后存入 Redis Hash,Key 为 "room:{房间ID}:users"
$this->redis->hset("room:{$roomId}:users", $username, json_encode($userInfo));
}
}
三、首次启动(必须先执行)
cd /Users/pllx/Web/Herd/chatroom
# 安装 Reverb WebSocket 服务器(已经完成)
composer require laravel/reverb predis/predis
# 安装 Horizon 队列管理(替代 queue:work,提供 Web 监控面板)
composer require laravel/horizon
# 发布配置文件
php artisan reverb:install
php artisan horizon:install
# 创建数据库(已经完成)
mysql -u root -proot -e "CREATE DATABASE IF NOT EXISTS chatroom CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
# 运行数据库迁移(迁移前检查原有迁移文件是否有用)
php artisan migrate
# 安装前端依赖
npm install (已经完成)
npm install laravel-echo pusher-js(已经完成)
npm run dev
开发时运行的服务:
php artisan reverb:start --debug # WebSocket 服务器 :8080
php artisan horizon # 队列 Worker(含 Web 监控 /horizon)
npm run dev # Vite 热更新
# HTTP 由 Herd 自动提供 chatroom.test
四、数据库迁移对照表
原 Access 表 → Laravel Migration 对应关系:
| 原 ASP 表 | Laravel 迁移文件 | Model 类 | 说明 |
|---|---|---|---|
user |
create_users_table |
User |
主用户表(默认迁移文件,需修改) |
room |
create_rooms_table |
Room |
聊天房间 |
| (内存) | create_messages_table |
Message |
消息归档(原用 Application 内存) |
sysparam |
create_sys_params_table |
SysParam |
系统参数 |
ip_lock |
create_ip_locks_table |
IpLock |
IP 封锁 |
record |
create_audit_logs_table |
AuditLog |
管理操作日志 |
guestbook |
create_guestbooks_table |
Guestbook |
留言板 |
calls |
create_friend_calls_table |
FriendCall |
好友呼叫 |
friendrq |
create_friend_requests_table |
FriendRequest |
好友申请 |
action |
create_actions_table |
Action |
表情/动作定义 |
admincz |
create_admin_logs_table |
AdminLog |
管理员操作统计 |
gg |
create_user_items_table |
UserItem |
道具(封口令等) |
scrollad |
create_scroll_ads_table |
ScrollAd |
滚动公告 |
hy / lh |
create_marriages_table |
Marriage |
婚姻关系 |
ip |
create_ip_logs_table |
IpLog |
IP 登录日志 |
room_des |
create_room_descriptions_table |
RoomDescription |
房间描述模板 |
批量生成迁移命令:
php artisan make:migration create_rooms_table
php artisan make:migration create_messages_table
php artisan make:migration create_sys_params_table
php artisan make:migration create_ip_locks_table
php artisan make:migration create_audit_logs_table
php artisan make:migration create_guestbooks_table
php artisan make:migration create_friend_calls_table
php artisan make:migration create_friend_requests_table
php artisan make:migration create_actions_table
php artisan make:migration create_admin_logs_table
php artisan make:migration create_user_items_table
php artisan make:migration create_scroll_ads_table
php artisan make:migration create_marriages_table
php artisan make:migration create_ip_logs_table
php artisan make:migration create_room_descriptions_table
五、推荐目录结构
app/
├── Events/ # WebSocket 广播事件(ShouldBroadcast)
│ ├── MessageSent.php # 消息发送(替代 NEWSAY.ASP)
│ ├── UserJoined.php # 用户进房(替代 INIT.ASP)
│ ├── UserLeft.php # 用户离开(替代 LEAVE.ASP)
│ ├── UserKicked.php # 踢人
│ ├── UserMuted.php # 封口
│ └── RoomTitleUpdated.php # 房间标题更新
│
├── Services/ # 业务逻辑服务层(纯 PHP,不含 HTTP 逻辑)
│ ├── ChatStateService.php # Redis 全局状态(替代 Application 对象)
│ ├── MessageFilterService.php # 敏感词/HTML 过滤
│ ├── AuthService.php # 登录验证逻辑
│ └── UserLevelService.php # 等级权限判断(替代 getLevel())
│
├── Http/
│ ├── Controllers/
│ │ ├── AuthController.php # DEFAULT.asp + CHECK.asp + CLOSE.ASP
│ │ ├── RegisterController.php # Reg.asp + addnewuser.asp
│ │ ├── ChatController.php # NEWSAY.ASP + INIT.ASP + LEAVE.ASP
│ │ ├── RoomController.php # ROOM*.ASP 系列
│ │ ├── UserController.php # USERSET + DOUSER + KILLUSER
│ │ ├── FriendController.php # addfriend + agreefriend 等
│ │ ├── GuestbookController.php # GUEST.ASP
│ │ └── Admin/
│ │ ├── AdminController.php
│ │ ├── UserManagerController.php
│ │ └── SystemController.php # VIEWSYS.ASP
│ │
│ ├── Middleware/
│ │ ├── ChatAuthenticate.php # 聊天室登录验证
│ │ └── LevelRequired.php # 等级权限中间件(用法:chat.level:5)
│ │
│ └── Requests/ # Form Request 验证
│ ├── LoginRequest.php
│ ├── SendMessageRequest.php
│ └── CreateRoomRequest.php
│
├── Models/
│ ├── User.php
│ ├── Room.php
│ ├── Message.php
│ ├── SysParam.php
│ ├── IpLock.php
│ └── ...
│
└── Jobs/
└── SaveMessageJob.php # 异步将消息持久化到 MySQL
bootstrap/
└── app.php # ⚠ Laravel 12:中间件/路由在此配置(无 Kernel.php)
routes/
├── web.php # 所有 HTTP 路由
├── api.php # API 路由(Horizon 监控等)
└── channels.php # WebSocket Presence Channel 鉴权
resources/
├── views/
│ ├── index.blade.php # 登录页(DEFAULT.asp)
│ ├── chat/
│ │ ├── frame.blade.php # 聊天主框架(CHAT.ASP)
│ │ └── room.blade.php # 消息区
│ └── ...
└── js/
├── app.js
└── chat.js # Laravel Echo 替代 newChat.js
六、具体开发任务计划
✅ 已完成
- 创建 Laravel 12 项目
- 安装
laravel/reverb、predis/predis - 创建 MySQL 数据库
chatroom - 配置
.env(MySQL root/root · Redis · Reverb · 时区 Asia/Shanghai)
🔲 第一阶段:数据库层(预计 1-2 天)
目标:所有表创建完毕,并完成基础 Seeder。
- 修改默认
users迁移,对应 ASPuser表字段(username/passwd/sex/user_level/exp_num/friends/headface/等) - 创建
rooms迁移(room_name/owner/auto/des/title/permit_level/door_open) - 创建
messages迁移(room_id/from_user/to_user/content/is_secret/font_color/action/sent_at) - 创建
sys_params迁移(alias/guidetxt/body) - 创建
ip_locks迁移(ip/end_time/act_level) - 创建
audit_logs迁移(occ_time/occ_env/stype) - 创建
guestbooks迁移(who/towho/secret/ip/post_time/text_title/text_body) - 创建
friend_calls迁移(who/towho/callmess/calltime/read) - 创建
friend_requests迁移(who/towho/sub_time) - 创建
actions迁移(act_name/alias/toall/toself/toother) - 创建
user_items迁移(name/gg/times/dayy/lx — 对应道具/封口令等) - 创建
scroll_ads迁移(ad_title/ad_link/ad_new_flag) - 创建
marriages迁移(hyname/hyname1/hytime/hygb/hyjb) - 创建
ip_logs迁移(ip/sdate/uuname) - 创建所有 Model 文件(含
$fillable、$casts、关联关系、中文 DocBlock) - 创建
SysParamSeeder(写入系统默认参数:maxpeople/namelength/maxsayslength 等) - 运行
php artisan migrate --seed,验证建表成功
🔲 第二阶段:Auth 认证(预计 1-2 天)
目标:用户能够登录、注册、退出。
LoginRequest(验证:username/password/captcha 验证码)AuthController::index()— 登录页(含验证码生成,替代session("regjm"))AuthController::check()— 登录验证(含 IP 封锁检查 + 密码 MD5/bcrypt 双模式)AuthController::logout()— 退出并清理 Redis 用户状态RegisterController::show()— 注册页RegisterController::store()— 注册逻辑(含 IP 注册频率限制)ChatAuthenticate中间件 — 检查 Session 是否有效,无则跳转登录页LevelRequired中间件 — 检查用户等级,不足则拒绝(chat.level:5)- 在
bootstrap/app.php注册以上中间件别名 - 登录 Blade 视图
resources/views/index.blade.php(仿原 DEFAULT.asp 样式) - 测试:注册 → 登录 → 退出完整流程
🔲 第三阶段:Redis 状态层(预计 1 天)
目标:ChatStateService 完整实现,替代原 Application 对象。
ChatStateService实现以下方法(全部带中文注释):userJoin(int $roomId, string $username, array $info): voiduserLeave(int $roomId, string $username): voidgetRoomUsers(int $roomId): arraypushMessage(int $roomId, array $message): voidgetNewMessages(int $roomId, int $lastId): arraynextMessageId(int $roomId): int(Redis 自增计数器)withLock(string $key, callable $callback): mixed(分布式锁)getSysParam(string $alias): string(读取系统参数,缓存1分钟)
MessageFilterService— 敏感词替换 + HTML 过滤(替代TrStr()/SHTM()函数)UserLevelService— 从 Redis 读取当前用户等级
🔲 第四阶段:WebSocket 广播(预计 1 天)
目标:Reverb 正常运行,前端能收到实时消息。
MessageSentEvent(implementShouldBroadcast)— 广播到room.{id}Presence ChannelUserJoinedEvent — 用户进入广播UserLeftEvent — 用户离开广播UserKickedEvent — 踢人广播(私有频道,只发给被踢人)UserMutedEvent — 封口广播RoomTitleUpdatedEvent — 标题更新广播routes/channels.php— Presence Channel 鉴权(验证等级 + 返回用户信息)resources/js/chat.js— Laravel Echo 接入(Echo.join('room.X').here().joining().leaving().listen())- 运行
php artisan reverb:start --debug,测试 WebSocket 连通性
🔲 第五阶段:聊天核心(预计 2-3 天)
目标:进房、发言、离开完整流程可用。
ChatController::init()— 进入房间(读取 Redis 用户列表 + 历史消息,替代 INIT.ASP)ChatController::send()— 发言(过滤 → 推 Redis →SaveMessageJob→ 广播 Event)ChatController::leave()— 离开房间(清 Redis → 广播UserLeft)SaveMessageJob— 实现ShouldQueue,异步写消息到messages表- 聊天 Blade 视图
resources/views/chat/frame.blade.php(主框架,含 Vite 引入) - 测试:登录 → 进房 → 发言 → 另一浏览器实时收到消息
🔲 第六阶段:房间管理(预计 2 天)
RoomController::list()— 房间列表(替代 ROOMLIST.ASP)RoomController::create()/store()— 创建房间(替代 NEWROOM.ASP)RoomController::edit()/update()— 修改设置(替代 ROOMSET.ASP)RoomController::destroy()— 删除/解散房间(替代 CUTROOM.ASP)RoomController::transfer()— 转让房主(替代 OVERROOM.ASP)- 对应 Blade 视图
🔲 第七阶段:用户管理(预计 2 天)
UserController::info()— 用户信息(替代 USERinfo.ASP)UserController::update()— 修改个人资料(替代 USERSET.ASP)UserController::kick()— 踢人(替代 KILLUSER.ASP,广播UserKicked)UserController::mute()— 封口(道具user_items表操作)UserController::changePassword()— 改密码(替代 chpasswd.asp)
🔲 第八阶段:管理后台(预计 3-5 天)
LevelRequired中间件 保护/admin路由(需 level=15)Admin\SystemController— 系统参数配置(替代 VIEWSYS.ASP)Admin\UserManagerController— 用户管理列表(替代gl/目录)Admin\SqlController— 后台 SQL 执行(替代 SQL.asp,⚠ 仅 SELECT)- Horizon 面板
/horizon(队列监控,替代后台日志查看) - 对应 Blade 视图
🔲 第九阶段:附加功能(按需)
- 好友系统(FriendController)
- 留言板(GuestbookController)
- 排行榜(RankController)
- 会员系统(
huiyuan/对应功能) - 滚动公告(ScrollAd 管理)
七、注意事项
7.1 密码兼容策略
- 导入旧数据时,
password字段存原始 MD5 值(32位字符串) - 登录时双模式验证:
md5($input) === $storedPass成功后升级为bcrypt - 新注册用户直接用
bcrypt(Hash::make()) - 约 3 个月后移除 MD5 兼容分支
7.2 字符编码
- 原 Access 数据库为 GBK 编码
- 所有 MySQL 表必须
utf8mb4_unicode_ci - 导入历史数据前转换:
iconv -f GBK -t UTF-8 原文件.csv > 目标文件_utf8.csv
7.3 REFRESH.ASP 已废弃
原系统的 6 秒 <meta http-equiv=refresh> 完全由 Reverb WebSocket 实时推送取代,无需任何轮询逻辑。
7.4 Application 对象替代
| 原 ASP | Laravel 替代 |
|---|---|
Application("_user_list") |
Redis::hgetall("room:{id}:users") |
Application("_says") 环形缓冲 |
Redis::lrange("room:{id}:messages", 0, 199) |
Application("_room_list") |
Redis::get("room:{id}:info") + rooms 表 |
Application.Lock/Unlock |
Cache::lock("key", 10)->block(5, fn) |
7.5 Flash 游戏(暂不处理)
game/、pig/、Gupiao/ 等目录内的 .swf Flash 文件现代浏览器已不支持,本期不做转换,后续单独用 HTML5/Canvas 重写。
八、常用命令速查
# 创建 Model + Migration(-m 同时生成迁移)
php artisan make:model Room -m
# 创建 Controller(-r 生成 RESTful 方法)
php artisan make:controller ChatController
# 创建广播 Event
php artisan make:event MessageSent
# 创建队列 Job
php artisan make:job SaveMessageJob
# 创建 Middleware
php artisan make:middleware ChatAuthenticate
# 创建 Form Request
php artisan make:request SendMessageRequest
# 重置迁移(开发阶段)
php artisan migrate:fresh --seed
# 查看路由列表
php artisan route:list --columns=method,uri,name,action
# 代码格式化(提交前必须运行)
vendor/bin/pint --dirty
# Horizon 队列监控(生产环境)
php artisan horizon
# 重启 Horizon(更新代码后)
php artisan horizon:terminate
# 清理所有缓存
php artisan optimize:clear
原 ASP 源码参考路径:
/Users/pllx/Web/chat/hp0709/数据库 SQL 参考:/Users/pllx/Web/chat/hp0709_php/database.sql