定制 rasuvaeff/yii3-ab-testing-web 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

rasuvaeff/yii3-ab-testing-web

最新稳定版本:v1.0.0

Composer 安装命令:

composer require rasuvaeff/yii3-ab-testing-web

包简介

Cookie identity and sticky-variant store for Yii3 A/B testing

README 文档

README

Stable Version Total Downloads Build Static Analysis PHP License

Web identity and sticky-variant layer for Yii3 A/B testing. Gives every visitor a stable subject id (so deterministic assignment holds across visits) and, when you need it, pins a subject to a variant across weight changes via a signed cookie.

Using an AI coding assistant? llms.txt contains a compact API reference you can ingest in your prompt context.

Requirements

  • PHP 8.3+
  • rasuvaeff/yii3-ab-testing ^1.2 (adds AssignmentStore and Assignment::isSticky)
  • yiisoft/cookies ^1.2
  • a PSR-7 implementation (e.g. nyholm/psr7) and a PSR-15 stack

Installation

composer require rasuvaeff/yii3-ab-testing-web

Identity vs stickiness

Assignment is deterministic in subjectId (sha256(salt:subjectId)), so a stable id alone keeps a visitor in the same variant across visits — no variant is stored. Two cookie roles solve two different problems:

Need Use
A stable id for anonymous visitors SubjectIdMiddleware (cookie ab_id)
Keep a variant even after weights/variants change CookieAssignmentStore + StickyAssignmentResolver

A logged-in user already has a stable id (userId) — set it as the request attribute upstream and the middleware leaves it alone.

Subject identity middleware

Add SubjectIdMiddleware to your PSR-15 stack. It resolves the subject id and exposes it as a request attribute (ab.subjectId by default):

  1. if the attribute is already set (an upstream auth middleware put userId there) it is kept — no cookie;
  2. otherwise the ab_id cookie is reused — only when its value matches the generated format (32 lowercase hex chars); a tampered or oversized value is discarded and regenerated;
  3. otherwise a new opaque id is generated and a long-lived HttpOnly, SameSite=Lax cookie is set.
use Rasuvaeff\Yii3AbTestingWeb\SubjectIdMiddleware;

$middleware = new SubjectIdMiddleware(); // defaults: cookie 'ab_id', attribute 'ab.subjectId'

// in your action/handler:
$subjectId = $request->getAttribute('ab.subjectId');
$assignment = $ab->assign(experiment: 'checkout-button', subjectId: $subjectId);

For most experiments this is all you need.

Sticky variants

Changing weights or the variant set shifts bucket boundaries and reshuffles subjects. To pin a subject across such changes, resolve through a CookieAssignmentStore (a signed {experiment: variant} cookie) and a StickyAssignmentResolver. Because the store is request-scoped, wire it in a thin middleware that reads the cookie, exposes the store, and writes it back:

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Rasuvaeff\Yii3AbTestingWeb\CookieAssignmentStore;
use Yiisoft\Cookies\CookieSigner;

final class StickyCookieMiddleware implements MiddlewareInterface
{
    public function __construct(private CookieSigner $signer) {}

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $store = CookieAssignmentStore::fromRequest($request, $this->signer);
        $response = $handler->handle($request->withAttribute('ab.store', $store));

        return $store->applyToResponse($response);
    }
}

Then in your action:

use Rasuvaeff\Yii3AbTestingWeb\StickyAssignmentResolver;

$store = $request->getAttribute('ab.store');                 // CookieAssignmentStore
$resolver = new StickyAssignmentResolver($ab, $store);

$assignment = $resolver->resolve(
    experiment: 'checkout-button',
    subjectId: $request->getAttribute('ab.subjectId'),
);
// first time: assigned and stored; later: the stored variant is returned

StickyAssignmentResolver keeps AbTesting::assign() pure: a forced variant bypasses the store, a disabled experiment returns its fallback (the kill switch always wins and nothing is stored), and a stored variant that is no longer part of the experiment is re-assigned.

API reference

Class Description
SubjectIdMiddleware PSR-15 middleware; stable subject id + ab_id cookie
CookieAssignmentStore AssignmentStore over one signed cookie; fromRequest() / applyToResponse()
StickyAssignmentResolver get-or-assign over AbTesting + any AssignmentStore

Security & privacy

  • The subject id is an opaque 128-bit token (random_bytes), not a UUID, and carries no personal data — but it is a persistent identifier. Set the cookie only after consent where the law requires it.
  • The sticky cookie is signed (yiisoft/cookies CookieSigner); a missing, unsigned, tampered, or malformed cookie is ignored and yields an empty store — never a partial or attacker-controlled variant map. Provide a strong signing key.
  • Cookies are HttpOnly, SameSite=Lax, and Secure by default.
  • The cookie is browser-scoped: the $subjectId argument of the store is ignored. A visitor who was anonymous then logged in keeps the variants from their anonymous identity.

Examples

See examples/ for a runnable script (no server required).

Development

composer build          # full gate: validate + normalize + cs + psalm + test
composer cs:fix         # auto-fix code style
composer psalm          # static analysis
composer test           # run tests

License

BSD-3-Clause. See LICENSE.md.

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: BSD-3-Clause
  • 更新时间: 2026-06-12

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固