Composer只是PHP依赖管理工具,不能直接解决A/B测试分组问题;必须用稳定用户标识(如userId)配合确定性哈希,并手动持久化结果,否则同一用户会反复变组。

Composer 是 PHP 的依赖管理工具,它本身不提供 A/B 测试逻辑,也不能“直接解决”数据分组问题。引入一个实验组件(比如 splitbrain/phpab 或自研 SDK)只是第一步,真正的分组逻辑、一致性保障、状态持久化,全得自己设计和验证。
为什么 composer require 后分组还是乱的?
常见现象:同一用户刷新页面,getVariation() 返回 A 和 B 交替出现;或不同设备登录同一账号,分组不一致。
- 根本原因在于多数轻量组件默认用
session_start()或内存缓存做分组决策,但 session 可能未开启、跨请求丢失,或缓存未命中时重新哈希 - 分组必须满足「同一用户 + 同一实验」始终返回相同变体,这需要稳定输入(如用户 ID、设备 ID、登录态 token)+ 确定性哈希(如
md5($userId . $experimentKey)) - 别依赖组件内置的“随机分配”,除非你明确配置了
sticky模式并传入稳定 key
splitbrain/phpab 的 getVariation() 怎么用才不翻车?
这个库默认行为是每次调用都可能变,不是开箱即用的 A/B 分组方案。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 必须手动传入唯一且稳定的
$userKey:$ab->getVariation('checkout_button', $userId),否则它会 fallback 到rand() - 确保
$userId在未登录时也有降级策略(如用$_COOKIE['device_id']或hash($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'])),但要注意隐私合规 - 它不自动存取结果,你需要配合
$_SESSION或 Redis 写一层 wrapper,例如:if (!isset($_SESSION['ab'][$experiment])) { $_SESSION['ab'][$experiment] = $ab->getVariation($experiment, $stableKey); } return $_SESSION['ab'][$experiment];
分组逻辑写在中间件还是业务层?
写在中间件看似统一,实则容易埋雷。
- 如果中间件提前执行分组并塞进
$request->attributes,但后续某步因异常跳过该中间件(如 API 路由未匹配、CORS 预检拦截),业务代码拿到的可能是空或旧值 - 更稳妥的是在真正需要变体的业务点(如渲染按钮前)调用分组函数,并把
$stableKey和$experimentKey作为参数显式传入,避免隐式依赖 - 务必加 fallback:当分组服务不可用(Redis 超时、哈希函数报错),应返回默认变体(如
A)并记录告警,而不是抛异常中断流程
分组不是“引入一个包就完事”的事——哈希算法选型、key 的稳定性、存储介质的一致性读写、灰度开关的隔离粒度,每个环节出问题都会让实验结论失效。最常被忽略的是:没在日志里打上 $stableKey 和实际分组结果,导致排查时完全无法还原用户路径。

















