silverstripe/personalisation

此包已被弃用且不再维护。作者建议使用silverstripe/personalisation包代替。

SilverStripe 个性化模块

dev-master 2016-05-05 04:21 UTC

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() 方法将被调用,并按照需求计算值。请注意,计算仅在需要时执行。

跟踪