silverstripe / personalisation
Requires
- silverstripe/cms: 3.0.*
This package is not auto-updated.
Last update: 2024-07-10 21:54:31 UTC
README
个性化模块
维护者联系方式
* Mark Stephens (mark@silverstripe.com)
* Carlos Barberis (carlos@silverstripe.com)
概述
本模块为 SilverStripe 应用程序提供个性化服务。可以在 CMS 中设置 个性化方案,并将这些方案渲染到模板或其他 UI 中。每个方案通常定义了 变体 和 规则,以确定在特定情况下呈现哪个变体。
变体体现表现行为。一些内置的变体包括
- 渲染可点击的图像
- 渲染文本
- 从 SilverStripe 模板渲染标记
开发人员可以定义新的变体。
规则在 上下文 中执行。这是一个可扩展的属性集合,具有管理员用户可以用来定义规则的值。属性组织在一个命名空间中。一些属性由模块预定义,但通常网站会通过自定义上下文处理器或通过跟踪器引入新的属性。
模块实现了基本的 跟踪,可以通过会话、成员登录或跟踪cookie跟踪用户在网站上的操作。跟踪器公开了一个简单的API,允许开发人员操作和查询跟踪器中存储的信息。
关键接口和类包括
- ContextProvider - 支持检索用于个性化决策的属性值的关键接口。
- DefaultContextProvider - ContextProvider 的默认实现,设计用于广泛的应用。预计所有具有此模块的网站都会使用它。其行为可以通过处理程序扩展。
- Tracker - 跟踪行为的关键接口。通常仅用于写入;读取通常通过 DefaultContextProvider 完成,当它需要时,会向跟踪器请求属性。
- TrackingStore - 需要实现跟踪信息存储的关键接口。这包括检索、存储和获取元数据。
- DefaultTrackingStore - 一个简单的 TrackingStore 实现,适用于较小规模的跟踪(例如。
状态
应将此模块视为 alpha 状态。当前包含的功能包括
- 用于定义基本个性化方案的 CMS 界面。
- 一组可查询的常见属性。
- 一个用于程序添加新属性的 API。
- 可以配置为使用不同类型的身份识别网站用户的跟踪器。
- 可以存储跟踪信息的跟踪存储。
尚未实现但计划的功能包括
- 额外的规则库,用于在跟踪存储中自动推导新属性,以及支持该过程的过程。
- 对变体渲染/点击的统计收集和报告。
- 对跟踪器的高级查询。
- 支持跟踪器数据的陈旧化和不同的置信水平。
安装
您需要 SilverStripe 3.0 或更高版本。将模块目录放入项目的顶级目录中,就像往常一样,然后执行 dev/build。
在CMS界面中会出现一个个性化标签页。默认情况下,它将启用默认跟踪器,该跟踪器使用SilverStripe数据库进行存储。
配置
该模块使用SilverStripe 3配置系统,并为个性化配置项提供默认值,项目可以根据需要覆盖这些值。
默认上下文提供者
DefaultContextProvider是ContextProvider的默认实现者,它维护一个处理程序列表(这些处理程序本身实现ContextProvider)。内置了两个处理程序,两者都处于启用状态
- DefaultContextHandler实现了一套属性,用于公开当前请求。
- TrackerContextHandler扩展了这个命名空间以包含Tracker功能。
默认配置位于personalisation/_config/default.yml
要定义自己的上下文处理程序,您可以
Tracker
跟踪由Tracker类执行。该类维护一个或多个实现TrackingStore接口的对象列表。
在使用之前,需要初始化Tracker。这是通过调用
Tracker::init();
这将初始化Tracker并将DefaultTrackingStore作为唯一的跟踪存储添加。
或者,如果您想实现自己的TrackingStore,可以按如下方式初始化Tracker
Tracker::init();
Tracker::self::add_store("mytracker", "MyTrackingStoreClass");
模块设计
关键信息结构包括
- 上下文,它是一组命名空间属性/值。
模块中的关键类和接口如下
- 个性化方案 - 用于生成渲染输出的个性化配置的持有者。
- ContextProvider - 一个接口,定义了用于确定个性化输出的属性的方法。这包括检索一个或多个属性以及检索这些属性元数据的方法。值得注意的实现者包括DefaultContextProvider和Tracker。
- DefaultContextProvider - 一个可以...
该模块根据以下原则构建
-
核心组件具有接口,以便在需要时可以替换不同的组件。
-
提供了这些接口的默认实现,并进行了配置,以便默认行为合理。
-
尽可能多的在需要时提供数据和状态,以最小化开销。
-
关于用户的已知状态是从每个请求中派生出来的。
-
每个请求可以携带一个或多个用于由一个或多个 跟踪身份查找器(TrackingIdentityFinder实现者)使用的状态,以便了解用户的 身份(TrackingIdentity)。
-
一个 跟踪器(Tracker)通过一个或多个 跟踪存储(TrackingStore实现者)管理针对身份记录的状态。
-
当需要派生个性化位置时,将调用一个 选择提供者(SelectionProvider实现者)来确定输出,通常是输出变体的标识符。
-
选择提供者可能具有任意规则或业务逻辑来做出其输出决策。
-
选择提供者提供了一个 上下文提供者,它使用它来查询有关用户的信息。
-
上下文提供者反过来从一个或多个处理程序中派生数据。
-
存在处理程序,允许上下文提供者从:跟踪器;原始请求;成员那里检索数据。也可以提供自定义处理程序。
-
如果选择提供者的输出标识了一个输出变体,那么将渲染该变体,并将其返回到启动上下文(例如,个性化项将出现的页面)。
自定义上下文处理程序
自定义处理程序是一个实现ContextProvider的类。其目的是以编程方式向属性命名空间引入新值。例如,您可能有一个函数,将请求中的地理位置信息映射到公司的地区办公室。
该接口有两个方法
- getProperties($properties) 方法用于获取由该处理器处理的属性值。处理器仅返回它理解的属性值。
- getMetadata($namespaces) 方法返回处理器理解的属性元数据。
例如,假设我们的项目需要在区域办事处进行个性化设置。我们想引入一个名为 request.regional-office 的属性,这样我们就可以在生成变体时使用它。该值最终将是一个字符串。
class OfficeContextHandler implements ContextProvider {
static $office_property = "request.regional-office";
function getProperties($properties) {
$result = array();
if (isset($properties[self::$office_property])) {
$v = $this->getRegionalOfficeFromRequest();
if ($v) {
$v = new ContextProperty(array(
"name" => $name,
"value" => $v,
"confidence" => 100 // we're completely sure of the request.
));
$v = array($v); // always an array, even for single values
$result[$name] = $v;
}
}
return $result;
}
// Return the office name, or null if we can't figure it out. We use ipinfodb.com to get lat/lng from IP,
// and then find the regional office closest to this location. This assumes you have a RegionalOffice
// class with Lat and Lng properties.
function getRegionalOfficeFromRequest() {
// http://api.ipinfodb.com/v3/ip-city/?key=<your_api_key>&ip=74.125.45.100&format=json
$req = new RestfulService("http://api.ipinfodb.com/v3/ip-city/");
$req->setQueryString(array('key' => self::get_ip_info_db_key(), 'ip' => $_SERVER['REMOTE_ADDR'], 'format' => 'json'));
$response = $req->request();
$data = json_decode($response->getBody());
$lng = $data->longitude;
$lat = $data->latitude;
$sql = "SELECT DISTINCT \"RegionalOffice\".\"ID\", (3959*acos(cos(radians($lat))*cos(radians(\"Lat\"))*cos(radians(\"Lng\")-radians($lng))+sin(radians($lat))*sin(radians(\"Lat\")))) AS distance FROM \"RegionalOffice\" ORDER BY \"distance\" ASC";
$sqlResult = DB::query($sql);
$results = $sqlResult->column("ID");
if(is_array($results)) {
$obj = DataObject::get_by_id("RegionalOffice", (int)$results[0]);
$method = self::get_output_method();
$content = $obj->$method();
return $content;
}
return null; // didn't find one
}
function getMetadata($namespaces = null) {
return array(
self::$office_property => "Text"
);
}
}
然后,在 mysite/_config.php 文件中
$this->register_handler(new OfficeContextHandler());
现在,每当调用个性化设置时,并且规则引用了属性 request.regional-office,getRegionalOfficeFromRequest() 方法将被调用,并按照需求计算值。请注意,计算仅在需要时执行。