datatester/datatester-php-sdk

此软件包最新版本(v3.0.0)没有提供许可证信息。

PHP Datatester SDK

v3.0.0 2023-02-28 09:31 UTC

This package is not auto-updated.

Last update: 2024-09-25 06:59:10 UTC


README

限制

此 SDK 仅支持 PHP 7.1 及更高版本。

先决条件

获取您项目的 App Key

  1. 前往 BytePlus 控制台 并登录您的账户。
  2. 产品 部分,点击 BytePlus 数据智能
  3. 项目列表 页面,对于要集成 SDK 的项目,在 操作 列下,点击 详情
  4. 社交媒体详情 弹出窗口中,复制 App Key

添加依赖

  1. 将此 SDK 下载到您项目的路径:git clone https://github.com/volcengine/datatester-php-sdk.git
├── src
├── datatester-php-sdk
├── composer.json
├── composer.lock
└── vendor
  1. 修改 composer.json 文件,添加 "repositories" 结构。
"repositories": [
        {
        "type": "path",
        "url": "./datatester-php-sdk/"
        }
    ]
  1. 通过运行以下代码在本地安装软件包。
composer require -W datatester/datatester-php-sdk

更改域名

默认域名必须按以下方式更改。源文件是 [Urls.php]。

const BASE_URL = 'https://datarangers.com';
const EVENT_URL = 'https://mcs.tobsnssdk.com/v2/event/list';

使用 SDK

以下是一个使用 PHP SDK 的代码示例。

use DataTester\Client\AbClient;

// Initialize the traffic-allocating object
// Find your app key by clicking "details" on the project list page on the BytePlus console
$abClient = new AbClient("${app_key}");
// The second value is the log interface. You can change it if you want
// The third value is for managing meta information. You can change it if you want
// The fourth value is for event tracking. You can change it if you want
// userAbInfoHandler is to ensure that incoming users do not leave the version. If you want to constantly store the information of incoming users, you can implement UserAbInfoHandler by yourself
// $abClient = new AbClient("ede2cd73482xxxxxx05bd1b24c1", $logger, $configManager, $eventDispatcher,$userAbInfoHandler);

// The user identifier for event tracking. You need to replace it with the actual user ID
$trackId = "uuid";

// The local user identifier. Not used for event tracking. You need to replace it with the actual user ID
$decisionId = "decisionID";

// When a user/device is not in this version, then the value of this parameter is returned. You can set its value as "null"
$defaultValue = true;

// User properties. Only used for allocating the traffic
$attributes = [];

// It is recommended that you use this interface
// The first parameter is the experiment key
$value = $abClient->activate(
    "${experiment_key}",
    $decisionId,
    $trackId,
    $attributes,
    $defaultValue);
if ($value) {
// The control version
} else {
// The variant version
}

API 参考

AbClient

初始化期间进行流量分配的类。

__construct(
    $token,
    LoggerInterface $logger = null,
    ProductConfigManagerInterface $productConfigManager = null,
    EventDispatcherInterface $eventDispatcher = null,
    UserAbInfoHandler $userAbInfoHandler = null
)

参数描述

activate

在流量分配后获取特定实验版本的配置,并自动跟踪暴露的事件。

如果要跟踪事件,请确保填写 trackId 字段。

activate($variantKey, $decisionId, $trackId, $attributes, $defaultValue): object

参数描述

返回值

用户输入的版本参数或用户/设备不在任何版本时的默认值。可以是字符串、数字、布尔值和 json 类型。以下是一个示例

// When the parameter type is string, the returned value is string "a";
// When the parameter type is number, the returned value is float 123.456;
// When the parameter type is boolean, the returned value is boolean true;
// When the parameter type is json, the returned value array ["key" => "a"].

activateWithoutImpression

在流量分配后获取特定实验版本的配置,但不跟踪暴露的事件。

activateWithoutImpression($variantKey, $decisionId, $attributes): array

参数描述

返回值

版本参数或空数组。以下是一个示例

variantKey=string:
        [
        'val' => 'b',
        'vid' => '36872'
        ]
variantKey=number:
        [
        'val' => 789.123,
        'vid' => '36872'
        ]
variantKey=json:
        [
            'val' => 
                [
                  'key' => 'b'
                ],
            'vid' => '36872'
        ]
variantKey=boolean:
        [
        'val' => false,
        'vid' => '36872'
        ]
]
variantKey=not_exist_key:
        []

getExperimentVariantName

获取用户输入的实验版本的名称

getExperimentVariantName($experimentId, $decisionId, $attributes): ?string

参数描述

返回值

用户输入的版本名称或用户/设备不在任何版本时的 "None"。以下是一个示例

getExperimentConfigs

获取用户输入的版本的相关详细信息

getExperimentConfigs($experimentId, $decisionId, $attributes): ?array

参数描述

返回值

用户输入的版本的详细信息或用户/设备不在该版本时的 'None'。以下是一个示例

[
  'string' => 
        [
        'val' => 'b',
        'vid' => '36872'
        ],
  'number' => 
        [
        'val' => 789.123,
        'vid' => '36872'
        ],    
  'json' => 
        [
            'val' => 
                [
                  'key' => 'b'
                ],
            'vid' => '36872'
        ],
  'boolean' => 
        [
        'val' => false,
        'vid' => '36872'
        ]
]

getAllExperimentConfigs

获取所有实验中所有版本的相关详细信息。

getAllExperimentConfigs($decisionId, $attributes): ?array

参数描述

返回值

用户输入的版本的详细信息或用户/设备不在任何版本时的空数组。以下是一个示例

[
  'string' => 
        [
        'val' => 'b',
        'vid' => '36872'
        ],
  'number' => 
        [
        'val' => 789.123,
        'vid' => '36872'
        ],    
  'json' => 
        [
            'val' => 
                [
                  'key' => 'b'
                ],
            'vid' => '36872'
        ],
  'boolean' => 
        [
        'val' => false,
        'vid' => '36872'
        ],
  'color' => 
        [
        'val' => 'red',
        'vid' => '36875'
        ]
]

getFeatureConfigs

获取用户加入的功能的相关详细信息

getFeatureConfigs($featureId, $decisionId, $attributes): ?array

参数描述

返回值

用户加入的功能变体的详细信息。如果用户/设备不在该功能中或该功能已禁用,则为 "None"。以下是一个示例

[
  'feature_key' => 
        [
        'val' => 'prod',
        'vid' => '20006421'
        ]
]

getAllFeatureConfigs

获取用户加入的所有功能的相关详细信息。

getAllFeatureConfigs($decisionId, $attributes): ?array

参数描述

返回值

用户加入的所有功能变体的详细信息。以下是一个示例

[
  'feature_key' => 
        [
        'val' => 'prod',
        'vid' => '20006421'
        ],
  'feature_key_color' => 
        [
        'val' => true,
        'vid' => '20006423'
        ]
]

getExperimentVariantNameWithImpression

获取用户输入的实验版本的名称。

WithImpression 接口接口自动跟踪事件。同时,如果想要跟踪事件,请确保在 activate 接口中填写 trackId 字段。

getExperimentVariantNameWithImpression($experimentId, $decisionId, $attributes): ?string

参数描述

返回值

用户输入的版本名称或用户/设备不在任何版本时的 "None"。以下是一个示例

getExperimentConfigsWithImpression

获取用户输入的版本的相关详细信息。

WithImpression 接口接口自动跟踪事件。同时,如果想要跟踪事件,请确保在 activate 接口中填写 trackId 字段。

getExperimentConfigsWithImpression($experimentId, $decisionId, $attributes): ?array

参数描述

返回值

用户输入的版本的详细信息或用户/设备不在该版本时的 'None'。以下是一个示例

[
  'string' => 
        [
        'val' => 'b',
        'vid' => '36872'
        ],
  'number' => 
        [
        'val' => 789.123,
        'vid' => '36872'
        ],    
  'json' => 
        [
            'val' => 
                [
                  'key' => 'b'
                ],
            'vid' => '36872'
        ],
  'boolean' => 
        [
        'val' => false,
        'vid' => '36872'
        ]
]

getFeatureConfigsWithImpression

获取用户加入的功能的相关详细信息

WithImpression 接口接口自动跟踪事件。同时,如果想要跟踪事件,请确保在 activate 接口中填写 trackId 字段。

getFeatureConfigsWithImpression($featureId, $decisionId, $attributes): ?array

参数描述

返回值

用户加入的功能变体的详细信息。如果用户/设备不在该功能中或该功能已禁用,则为 "None"。以下是一个示例

[
  'feature_key' => 
        [
        'val' => 'prod',
        'vid' => '20006421'
        ]
]

其他

为了更好地使用SDK,提供了一些建议。

LoggerInterface

日志接口提供了默认实现;如有业务需求,可以自定义实现类,在实例化AbClient时使用。

ProductConfigManagerInterface

元管理接口:请求元服务以拉取应用下的实验和特征信息。默认实现在每次实例化AbClient时实时拉取;如有业务需求,可以自定义实现类,在实例化AbClient时使用。

建议

建议使用redis缓存元信息,以避免每次初始化AbClient时都进行拉取。

以下是一个示例

$client = new AbClient("token", null, new RedisConfigManager("token"));

class RedisConfigManager implements ProductConfigManagerInterface
{
    /**
     * @var ProductConfig $_productConfig
     */
    private $_productConfig;

    /**
     * @var LoggerInterface Logger instance.
     */
    private $_logger;

    /**
     * @var string $_token
     */
    private $_token;

    public function __construct(
        $token
    )
    {
        $this->_logger = new DefaultLogger();
        $this->_token = $token;
    }

    public function getConfig(): ?ProductConfig
    {
        if ($this->_productConfig != null) {
            return $this->_productConfig;
        }
        $valueFromRedis = $this->getValueFromRedis("tester_meta_info");
        // pull meta when redis cache expired
        if ($valueFromRedis == null) {
            $productConfigManger = new HTTPProductConfigManager($this->_token);
            try {
                $metaInfo = $productConfigManger->getMeta();
                $this->setValue2Redis("tester_meta_info", JsonParse::transferArray2JsonStr($metaInfo), 60);
                $this->_productConfig = new ProductConfig($metaInfo, $this->_logger);
                return $this->_productConfig;
            } catch (\Exception $e) {
                return null;
            }
        }
        $metaInfo = JsonParse::transferJsonStr2Array($valueFromRedis);
        $this->_productConfig = new ProductConfig($metaInfo, $this->_logger);
        return $this->_productConfig;
    }

    private function getValueFromRedis(string $key): ?string
    { 
        // need to implement it yourself
        // return redis.get($key);
        return null;
    }

    private function setValue2Redis(string $key, string $value, int $expire)
    {
        // need to implement it yourself
        // redis.set($key, $value, $expire);
    }
}

EventDispatcherInterface

事件跟踪接口:跟踪曝光事件,提供默认实现,在调用'activate'和'WithImpression'接口时实时跟踪;如有业务需求,可以自定义实现类,在实例化AbClient时使用。

建议

建议使用mq(kafka/rocketmq)跟踪事件,以避免每次调用接口时通过http跟踪事件。

  1. 事件发生时发送消息到mq
  2. 使用其他服务消费kafka并跟踪事件

以下是一个示例

$client = new AbClient("token", null, null, new KafkaEventDispatcher());

class KafkaEventDispatcher implements EventDispatcherInterface
{
    public function dispatchEvent($events)
    {
        // need to implement it yourself
        kafka.send(JsonParse::transferArray2JsonStr($events));
    }
}

UserAbInfoHandler

维护用户历史决策信息;如需使用“冻结实验”或“流量变化不影响曝光用户”的功能,可以自定义实现类,在实例化AbClient时使用。

建议

建议使用redis缓存决策信息。

以下是一个示例

$client = new AbClient("token", null, null, null, new RedisHandler());

class RedisHandler implements UserAbInfoHandler
{
    public function query(string $decisionId): ?string
    {
        // need to implement it yourself
        return redis.get($decisionId);
    }

    public function createOrUpdate(string $decisionId, string $experiment2variantStr): bool
    {
        // need to implement it yourself
        return redis.set($decisionId, $experiment2variantStr);
    }

    public function needPersistData(): bool
    {
        // return true if customize this interface
        return true;
    }
}

匿名跟踪

如果没有用户_unique_id作为跟踪ID,可以使用device_id、web_id、bddid(仅限本地)进行匿名跟踪。

  1. 设置事件构建器配置
enable anonymously tracking
$this->_abClient->setEventBuilderConfig(true, true);
  1. 当trackId为空字符串时,将device_id、web_id、bddid附加到$attributes中
$trackId = "";
$attributes["device_id"] = 1234; int
$attributes["web_id"] = 5678; int
$attributes["bddid"] = "91011"; string
  1. 调用activate或其他'WithImpression'接口

DataTester PHP SDK

版本需求

php7.1及更高版本

准备工作

获取应用的App Key(即SDK使用的token)

  1. 访问火山引擎并登录您的账号
  2. 进入集团设置页面,找到应用列表-应用ID列
  3. 将鼠标悬停在应用ID后的感叹号上以获取App Key

依赖导入

  1. 将SDK下载到项目路径下: git clone https://github.com/volcengine/datatester-php-sdk.git
├── src
├── datatester-php-sdk
├── composer.json
├── composer.lock
└── vendor
  1. 修改项目的composer.json文件,添加repositories结构
"repositories": [
        {
        "type": "path",
        "url": "./datatester-php-sdk/"
        }
    ]
  1. 安装本地包
composer require -W datatester/datatester-php-sdk

域名修改

SaaS-国内: 默认使用的是SaaS国内环境的域名,无需修改

const BASE_URL = 'https://data.bytedance.com';
const EVENT_URL = 'https://mcs.ctobsnssdk.com/v2/event/list';

SaaS-海外: 海外环境需要修改BASE_URL和EVENT_URL,替换为BASE_URL_I18N与EVENT_URL_I18N即可

修改如下
const BASE_URL = 'https://datarangers.com';
const EVENT_URL = 'https://mcs.tobsnssdk.com/v2/event/list';

私有化: 私有化部署时会有产品域名和上报域名,如下所示,BASE_URL替换为产品域名,EVENT_URL替换为上报域名

例如:产品域名为product.cc,上报域名为product.com,则修改如下
const BASE_URL = 'https://product.cc';
const EVENT_URL = 'https://product.com/v2/event/list';

代码示例

use DataTester\Client\AbClient;

// 初始化ABTest分流类,token获取方式详见接口描述-AbClient
$abClient = new AbClient("ede2cd734827cccf9c051005bd1b24c1");
// 第2个缺省值,日志接口,可根据业务需要传入自定义实现类,SDK提供默认实现
// 第3个缺省值,实验Meta信息管理接口,可根据业务需要传入自定义实现类,SDK提供默认实现
// 第4个缺省值,进组曝光事件上报接口,可根据业务需要传入自定义实现类,SDK提供默认实现
// 第5个缺省值,进组信息持久化接口,可根据业务需要传入自定义实现类,SDK提供默认实现(不持久化)
// $abClient = new AbClient("ede2cd734827cccf9c051005bd1b24c1", $logger,      $configManager, $eventDispatcher,$userAbInfoHandler);

// trackId 事件上报用户标识,用于事件上报,请替换为客户的真实用户标识
$trackId = "uuid";
// decisionID: 本地分流用户标识,不用于事件上报,请替换为客户的真实用户标识
$decisionId = "decisionID";
// defaultValue: 当分流未命中时返回该值,根据业务需要使用,可传null
$defaultValue = "default_value";
// attributes: 用户属性,仅用于分流,不随埋点上报,可参考https://www.volcengine.com/docs/6287/65826
$attributes = [];

// 推荐接口 abtest_param为需要通过分流下发的参数名称
$value = $abClient->activate(
    "abtest_param",
    $decisionId,
    $trackId,
    $attributes,
    $defaultValue);
if ($value === "param_raw") {
// 对照组
} elseif ($value === "param_test") {
// 实验组
} else {
// 默认处理
}

接口描述

AbClient

初始化ABTest分流类

__construct(
    $token,
    LoggerInterface $logger = null,
    ProductConfigManagerInterface $productConfigManager = null,
    EventDispatcherInterface $eventDispatcher = null,
    UserAbInfoHandler $userAbInfoHandler = null
)

参数

activate

获取特定key的分流结果,并上报曝光事件

activate($variantKey, $decisionId, $trackId, $attributes, $defaultValue): object

参数

返回值

该函数返回命中版本的参数值,未命中时返回默认值

参数类型为string,返回值为string "a"
参数类型为number,返回值为float  123.456
参数类型为boolean,返回值为boolean true
参数类型为json,返回值为array ["key" => "a"]

activateWithoutImpression

获取特定key的分流结果,且不上报曝光事件

activateWithoutImpression($variantKey, $decisionId, $attributes): array

参数

返回值

该函数返回命中版本的参数值,未命中时返回空数组

variantKey=string:
        [
        'val' => 'b',
        'vid' => '36872'
        ]
variantKey=number:
        [
        'val' => 789.123,
        'vid' => '36872'
        ]
variantKey=json:
        [
            'val' => 
                [
                  'key' => 'b'
                ],
            'vid' => '36872'
        ]
variantKey=boolean:
        [
        'val' => false,
        'vid' => '36872'
        ]
]
variantKey=not_exist_key:
        []

getExperimentVariantName

获取用户命中的特定实验的变体名称

getExperimentVariantName($experimentId, $decisionId, $attributes): ?string

参数

返回值

该函数返回用户命中的特定实验的变体名称

getExperimentConfigs

获取用户命中的特定实验的变体详情

getExperimentConfigs($experimentId, $decisionId, $attributes): ?array

参数

返回值

该函数返回命中变体的array对象,表明用户命中某个实验的变体详情,通常仅能命中一个变体

[
  'string' => 
        [
        'val' => 'b',
        'vid' => '36872'
        ],
  'number' => 
        [
        'val' => 789.123,
        'vid' => '36872'
        ],    
  'json' => 
        [
            'val' => 
                [
                  'key' => 'b'
                ],
            'vid' => '36872'
        ],
  'boolean' => 
        [
        'val' => false,
        'vid' => '36872'
        ]
]

getAllExperimentConfigs

获取用户命中的所有实验的变体详情

getAllExperimentConfigs($decisionId, $attributes): ?array

参数

返回值

该函数返回命中变体的array对象,表明用户命中所有实验的变体详情,通常命中多个变体

[
  'string' => 
        [
        'val' => 'b',
        'vid' => '36872'
        ],
  'number' => 
        [
        'val' => 789.123,
        'vid' => '36872'
        ],    
  'json' => 
        [
            'val' => 
                [
                  'key' => 'b'
                ],
            'vid' => '36872'
        ],
  'boolean' => 
        [
        'val' => false,
        'vid' => '36872'
        ],
  'color' => 
        [
        'val' => 'red',
        'vid' => '36875'
        ]
]

getFeatureConfigs

获取用户命中的特定feature的变体详情

getFeatureConfigs($featureId, $decisionId, $attributes): ?array

参数

返回值

该函数返回命中变体的array对象,表明用户命中某个feature的变体详情,通常仅能命中一个变体

[
  'feature_key' => 
        [
        'val' => 'prod',
        'vid' => '20006421'
        ]
]

getAllFeatureConfigs

获取用户命中的所有feature的变体详情

getAllFeatureConfigs($decisionId, $attributes): ?array

参数

返回值

该函数返回命中变体的array对象,表明用户命中所有feature的变体详情,通常命中多个变体

[
  'feature_key' => 
        [
        'val' => 'prod',
        'vid' => '20006421'
        ],
  'feature_key_color' => 
        [
        'val' => true,
        'vid' => '20006423'
        ]
]

1、含有“WithImpression”字样的接口均会自动上报曝光事件

2、请务必填写trackId字段,否则会导致上报失效

getExperimentVariantNameWithImpression

同接口“getExperimentVariantName”

getExperimentConfigsWithImpression

同接口“getExperimentConfigs”

getFeatureConfigsWithImpression

同接口“getFeatureConfigs”

其他

LoggerInterface

日志打印接口,提供默认实现;如有业务需要,可自定义实现类处理,实例化AbClient时传入

ProductConfigManagerInterface

配置管理接口,请求meta服务拉取应用下的实验信息,提供默认实现,每次实例化AbClient时实时拉取;如有业务需要,可自定义实现类处理,实例化AbClient时传入

PHP本身不支持内存级别的缓存,可以通过文件(大多数第三方库的选择)或者借助Redis等进行缓存,通过定时任务去拉取meta信息,避免实时拉取

使用Redis缓存示例(仅供参考)

$client = new AbClient("token", null, new RedisConfigManager("token"));

class RedisConfigManager implements ProductConfigManagerInterface
{
    /**
     * @var ProductConfig $_productConfig
     */
    private $_productConfig;

    /**
     * @var LoggerInterface Logger instance.
     */
    private $_logger;

    /**
     * @var string $_token
     */
    private $_token;

    public function __construct(
        $token
    )
    {
        $this->_logger = new DefaultLogger();
        $this->_token = $token;
    }

    public function getConfig(): ?ProductConfig
    {
        if ($this->_productConfig != null) {
            return $this->_productConfig;
        }
        $valueFromRedis = $this->getValueFromRedis("tester_meta_info");
        // pull meta when redis cache expired
        if ($valueFromRedis == null) {
            $productConfigManger = new HTTPProductConfigManager($this->_token);
            try {
                $metaInfo = $productConfigManger->getMeta();
                $this->setValue2Redis("tester_meta_info", JsonParse::transferArray2JsonStr($metaInfo), 60);
                $this->_productConfig = new ProductConfig($metaInfo, $this->_logger);
                return $this->_productConfig;
            } catch (\Exception $e) {
                return null;
            }
        }
        $metaInfo = JsonParse::transferJsonStr2Array($valueFromRedis);
        $this->_productConfig = new ProductConfig($metaInfo, $this->_logger);
        return $this->_productConfig;
    }

    private function getValueFromRedis(string $key): ?string
    { 
        // need to implement it yourself
        // return redis.get($key);
        return null;
    }

    private function setValue2Redis(string $key, string $value, int $expire)
    {
        // need to implement it yourself
        // redis.set($key, $value, $expire);
    }
}

EventDispatcherInterface

事件上报接口,上报进组曝光事件,提供默认实现,调用activate与WithImpression接口时实时上报;如有业务需要,可自定义实现类处理,实例化AbClient时传入

不使用扩展PHP并不支持多线程,可以通过第三方库或者使用mq等进行异步发送,避免实时上报

基于kafka等消息队列,在实例化AbClient对象时传入EventDispatcherInterface的实现类;事件直接写入kafka,通过其他服务去消费kafka并上报(上报可参考 DefaultEventDispatcher的实现),写入和消费kafka的逻辑需自行实现

$client = new AbClient("token", null, null, new KafkaEventDispatcher());

class KafkaEventDispatcher implements EventDispatcherInterface
{
    public function dispatchEvent($events)
    {
        // need to implement it yourself
        kafka.send(JsonParse::transferArray2JsonStr($events));
    }
}

UserAbInfoHandler

用户信息处理接口,冻结实验、进组不出组场景下使用

冻结实验和进组不出组需要持久化用户的进组信息,SDK提供的默认实现不进行数据持久化;如有业务需要,则实现UserAbInfoHandler接口,结合Redis或其他外部存储对用户进组信息进行持久化处理,初始化AbClient时传入。使用方式:

  1. 初始化AbClient时不传入UserAbInfoHandler,则默认使用空实现,不启用“进组不出组”功能
  2. 继承UserAbInfoHandler接口,自行实现持久化存储;初始化AbClient时通过构造函数传入

使用Redis缓存示例(仅供参考)

$client = new AbClient("token", null, null, null, new RedisHandler());

class RedisHandler implements UserAbInfoHandler
{
    public function query(string $decisionId): ?string
    {
        // need to implement it yourself
        return redis.get($decisionId);
    }

    public function createOrUpdate(string $decisionId, string $experiment2variantStr): bool
    {
        // need to implement it yourself
        return redis.set($decisionId, $experiment2variantStr);
    }

    public function needPersistData(): bool
    {
        // return true if customize this interface
        return true;
    }
}

匿名上报

无法获取uuid的用户,可以通过填充device_id或web_id进行事件上报(私有化场景下也支持bddid)

  1. 实例化AbClient后修改事件上报相关配置,setEventBuilderConfig第一个参数(true/开启,false/关闭)匿名上报,第二个参数(true/saas,false/私有化)
enable anonymously tracking
$this->_abClient->setEventBuilderConfig(true, true);
  1. 将device_id、web_id、bddid添加到用户属性$attributes中,trackId固定传入空字符串""
$trackId = "";
$attributes["device_id"] = 1234; int
$attributes["web_id"] = 5678; int
$attributes["bddid"] = "91011"; string
  1. 请求activate或其他'WithImpression'接口即可匿名上报