crazycodr/data-transform

此包已被废弃,不再维护。未建议替代包。

用于从可枚举源转换数据

2.0.2 2013-08-22 16:02 UTC

This package is auto-updated.

Last update: 2022-02-01 12:26:31 UTC


README

此包包含将来自任何可枚举源的实时迭代数据轻松转换的功能。

此类具有一个变换迭代器,并附带不同类,您可以使用这些类从任何可迭代的源转换传入数据。

目录

  1. 安装
  2. 创建基本变换迭代器
  3. 同时支持多个变换器
  4. 在迭代器上下文外使用组件
  5. 创建可测试的类

安装

要安装它,只需将此需求包含到您的composer.json中

{
    "require": {
        "crazycodr/data-transform": "2.*"
    }
}

然后根据需要运行composer install/update。

创建基本变换迭代器

创建变换迭代器至少需要三项

  1. TransformerContainer,用于包含迭代器的不同变换器
  2. TransformingIterator,用于迭代数据并提供变换功能
  3. Transformer,用于将当前数据转换为新的数据

(注意:此代码假设您有一个基于数组的源数据,具有列:姓名、类型、性别和出生日期)

(注意:此代码假设您有一个名为Employe的类,模拟前面的源数据,并有一个新的属性:年龄)

//Create an employee transformer
$employeeTransformer = new ClosureTransformer(function($data, $key, $previous){ 
	$result = new Employee();
	$result->setName($data['name']);
	$result->setType($data['type']);
	$result->setSex($data['sex']);
	$result->setBirthdate($data['birthdate']);
	return $result;
});
$iterator = new TransformingIterator(new TransformerContainer(), $data);
$iterator->addTransformer($employeeTransformer);

//Iterate our data source and automatically only get males
foreach($iterator as $employee)
{
	echo 'Employee: '.$employee->getName().'<br>';
}

同时支持多个变换器

您可以将许多变换器一次性添加到变换容器中。目标是分离不同的变换方面。

此示例演示第一个变换器创建员工,但第二个手动初始化其他属性。 (年龄与出生日期)请注意,第二个变换器必须使用$previous变量来获取当前变换对象的状态,您不想再次重新创建对象。

//Create an employee transformer
$employeeTransformer = new ClosureTransformer(function($data, $key, $previous){ 
	$result = new Employee();
	$result->setName($data['name']);
	$result->setType($data['type']);
	$result->setSex($data['sex']);
	$result->setBirthdate($data['birthdate']);
	return $result;
});
$ageCalculatorTransformer = new ClosureTransformer(function($data, $key, $previous){ 
	$birthday = new DateTime($previous->getBirthday());
	$interval = $birthday->diff(new DateTime());
	$previous->setAge($interval->y);
	return $previous;
});
$iterator = new TransformingIterator(new TransformerContainer(), $data);
$iterator->addTransformer($employeeTransformer);
$iterator->addTransformer($ageCalculatorTransformer);

//Iterate our data source and automatically only get males
foreach($iterator as $employee)
{
	echo 'Employee: '.$employee->getName().' is '.$employee->getAge().' years old<br>';
}

在迭代器上下文外使用组件

您不需要使用变换迭代器... ClosureTransformer和TransformerContainer可以在循环外使用。正常使用具体/非具体类构建变换器,并使用一些数据调用"transform"。

//See code in previous snipet
$container = new TransformerContainer();
$container->addTransformer($employeeTransformer);
$container->addTransformer($ageCalculatorTransformer);

$result = $container->transform($data, null);

创建可测试的类

此库的目的是不需要每次都创建迭代器和它们子组件,并且可以轻松测试所有组件。为此,只需创建迭代器和子组件的具体扩展,然后进行测试。

class EmployeeTransformer extends ClosureTransformer
{
	public function __construct()
	{
		parent::__construct(function($data, $key, $previous){ 
			$result = new Employee();
			$result->setName($data['name']);
			$result->setType($data['type']);
			$result->setSex($data['sex']);
			$result->setBirthdate($data['birthdate']);
			return $result;
		});
	}
}
class EmployeeTransformingIterator extends TransformingIterator
{
	public function __construct($data)
	{
		parent::__construct(new TransformerContainer(), $data);
		$this->addTransformer(new EmployeeTransformer());
	}
}

这可能看起来有些极端,但这样您就创建了一个具体的功能类,可以重用和测试。请注意,DataProviders是测试组件的好方法,但在测试迭代器时使用它看起来会有些奇怪。

class EmployeeTransformerTest extends PHPUnit_Framework_TestCase
{

	/**
	* @dataProvider employeeTransformerDataProvider
	*/
	public function testTransform($data)
	{
		$transformer = new EmployeeTransformer();
		$this->assertEquals($data['expected'], $transformer->transform($data['testdata'], null));
	}
	
	public function employeeTransformerDataProvider()
	{
		//To contain the results returned by the data provider
		$result = array();
		
		//Item 1
		$emp = new Employee();
		$emp->setName('John doe');
		$emp->setBirthdate('1768-01-01');
		$emp->setSex('male');
		$result[] = array(
			'expected' => $emp,
			'testdata' => array('name' => 'John doe', 'birthdate' => '1768-01-01', 'sex' => 'male'),
		);
		
		//Item 2
		$emp = new Employee();
		$emp->setName('Jane doe');
		$emp->setBirthdate('1768-01-01');
		$emp->setSex('female');
		$result[] = array(
			'expected' => $emp,
			'testdata' => array('name' => 'Jane doe', 'birthdate' => '1768-01-01', 'sex' => 'female'),
		);
		
		return $results;
		
	}
	
}