workerman 不支持 aop 但可通过生命周期回调和中间件模式模拟切面行为:onconnect/onmessage/onclose/onerror 对应前置/环绕/后置/异常通知,用函数链封装横切逻辑,注意连接属性的合理使用与清理。

Workerman 本身不支持 AOP,但可以模拟切面行为
Workerman 是事件驱动的 PHP 网络框架,没有 IoC 容器、代理机制或切点表达式引擎,@Aspect、@Pointcut、@Before 这类 Spring AOP 的语义在它里面完全不存在。你不能直接“开启 AOP”或“扫描注解”,所有逻辑必须显式编写、手动注册。但你可以用函数组合 + 回调封装 + 连接生命周期钩子,逼近 AOP 的关注点分离效果。
用 Connection 对象生命周期事件模拟通知类型
Workerman 的 $connection 实例天然提供四个关键回调入口:onConnect、onMessage、onClose、onError。这正好对应 AOP 的前置、环绕(消息处理)、后置/最终、异常通知场景。关键不是“复刻语法”,而是把共性逻辑(如日志、鉴权、心跳统计)抽离成独立函数,在这些回调中统一调用。
-
onConnect:适合做连接准入控制(IP 白名单、token 解析)、初始化连接上下文($connection->uid = ...) -
onMessage:可包装为“环绕”逻辑——先校验消息格式/权限,再调用业务 handler,最后记录耗时和返回码 -
onClose:清理资源(从 Redis 连接池移除 session)、广播下线事件、更新在线状态 -
onError:捕获底层 socket 错误,避免进程崩溃,同时记录错误堆栈(注意不要 throw)
如何避免重复写“横切代码”?用中间件模式封装
不要在每个 Worker::onMessage 里都写一遍 log()->info(...) 和 checkAuth(...)。定义一个轻量中间件函数链:
function wrapWithMiddleware($handler, ...$middlewares) {
return function ($connection, $data) use ($handler, $middlewares) {
foreach ($middlewares as $middleware) {
if ($middleware($connection, $data) === false) {
return; // 中断后续执行
}
}
$handler($connection, $data);
};
}
<p>// 使用示例
$worker->onMessage = wrapWithMiddleware(
function ($conn, $data) { /<em> 核心业务 </em>/ },
function ($conn, $data) { /<em> 日志中间件 </em>/ },
function ($conn, $data) { /<em> 权限中间件 </em>/ },
function ($conn, $data) { /<em> 统计中间件 </em>/ }
);
</p>
这种写法不依赖任何框架扩展,零配置,但要求你手动维护执行顺序。注意中间件内部不能阻塞(比如同步 MySQL 查询),否则会拖垮整个事件循环。
真正容易被忽略的点:连接对象不是“无状态”的,别滥用属性
很多人习惯往 $connection 上挂临时属性(如 $connection->authed = true、$connection->start_time = microtime(true)),这是可行的,但必须清楚两点:
- 这些属性只对当前连接有效,不会跨连接共享,也不参与序列化
- 如果在
onClose里没清理自定义属性(尤其是大数组或资源句柄),可能造成内存缓慢泄漏——Workerman 不会自动回收连接对象上的动态属性 - 多个中间件往同一个 key 写值(比如都设
$connection->user)会产生覆盖,建议用命名空间前缀,如$connection->middleware_auth_user











