nylle / php-automapper
This package is not auto-updated.
Last update: 2024-09-20 19:14:42 UTC
README
PHP 版本的著名 .NET AutoMapper,自动将一个对象的属性映射到另一个对象。
PHP 有所不同
PHP 不是类型安全的。虽然支持数组、类和接口的函数参数类型提示,但无法指定返回类型。
为了确保安全映射,PHP AutoMapper 需要遵守一些约定。
约定
- 只有公共属性会被映射。受保护的或私有的属性以及方法、获取器和设置器将被忽略。
- 目标类的属性需要具有适当的 PHPDoc 元素,形式如下:
/** @var type */
- 任何标量类型(int、integer、bool、boolean、float、double、real、string)都会被复制,而不会进行进一步的检查(请参阅 PHP 的 类型转换)。
- 类型
/** @var array */
被认为是标量类型的简单数组,因此它们会被复制而不会进行进一步的检查,同时保留键。 - 对象类型需要包含完整的命名空间和类名,形式如下:
/** @var Full\Name\Space\ClassName */
- 对于对象数组,类型需要是包括命名空间在内的完整类名,后面跟着空方括号:
/** @var NameSpace\ClassName[] */
。键将不会保留。
使用方法
默认情况下,所有具有相同名称的属性都会从源对象映射到目标对象。标量将被复制,对象将被递归映射。
映射具有不同名称的属性
在创建映射时,目标和源属性需要是包含类名(包括命名空间)以及属性名(用作用域解析运算符 ::
分隔)的完全限定字符串。这样,只有指定类的属性会被映射,但嵌套对象中具有相同名称的属性将被故意忽略。因此,对于每个期望的类,每个具有不同名称的目标/源属性对都需要进行映射。
$mapper = new \Adminomatic\AutoMapper\Mapper();
$mapper->CreateMap('NameSpace\DestinationClass::MyProperty', 'NameSpace\SourceClass::DifferentlyNamedProperty');
$mapper->CreateMap('NameSpace\SubClass::MyProperty', 'NameSpace\SourceSubClass::DifferentlyNamedProperty');
$myDestinationObject = $mapper->Map(new \NameSpace\DestinationClass(), $sourceObject);
指定自定义类型转换器
只能为映射属性对指定 ITypeConverter
。否则,转换器将用于所有属性。
$mapper = new \Adminomatic\AutoMapper\Mapper();
$mapper->CreateMapUsingConverter('DestinationClass::MyProperty',
'SourceClass::DifferentlyNamedProperty',
new \Adminomatic\AutoMapper\ImplodeConverter());
$myDestinationObject = $mapper->Map(new DestinationClass(), $sourceObject);
要为多个属性使用相同的转换器,需要为每种情况创建一个映射。
$myImplodeConverter = new \Adminomatic\AutoMapper\ImplodeConverter();
$mapper = new \Adminomatic\AutoMapper\Mapper();
$mapper->CreateMapUsingConverter('DestinationClass::MyProperty', 'SourceClass::DifferentlyNamedProperty', $myImplodeConverter);
$mapper->CreateMapUsingConverter('DestinationClass::OtherProperty', 'SourceClass::AnotherProperty', $myImplodeConverter);
$myDestinationObject = $mapper->Map(new DestinationClass(), $sourceObject);
记住:每个属性都必须通过包括命名空间和类名,然后是作用域解析运算符和属性名来完全限定。
从多个源值解析目标属性值
有时,目标属性期望的值依赖于源对象的多个属性。想象你有一个具有属性 PersonDTO->FirstName
和 PersonDTO->LastName
的源类 PersonDTO
,但你希望将这些组合成目标属性 PersonModel->FullName
。指定你的 IValueResolver
实现来处理这些情况。值解析器将始终获取父对象以使用属性,因此不能指定源属性。
$mapper = new \Adminomatic\AutoMapper\Mapper();
$mapper->CreateMapUsingResolver('NameSpace\DestinationClass::MyProperty', new \CustomResolver());
$myDestinationObject = $mapper->Map(new \NameSpace\DestinationClass(), $sourceObject);
API
PHP AutoMapper 包含用于创建自己的类型转换器和值解析器的接口。
ITypeConverter
ITypeConverter::Convert()
方法期望源属性值并返回目标属性转换后的值。
namespace Adminomatic\AutoMapper {
interface ITypeConverter {
function Convert($source);
}
}
包含的类型转换器
PHP AutoMapper 包含两个简单易用的类型转换器。
CountConverter
namespace Adminomatic\AutoMapper {
class CountConverter implements ITypeConverter {
public function Convert($source) {
return \count($source);
}
}
}
CountConverter
期望输入为一个数组,并返回元素的数量。
一个可能的例子是,一个包含评论数组的博客帖子 DTO,你想要将评论数组转换成博客帖子模型中的整数值,简单地显示该帖子的评论数量。
ImplodeConverter
namespace Adminomatic\AutoMapper {
class ImplodeConverter implements ITypeConverter {
private $delimiter;
public function __construct($delimiter='') {
$this->delimiter = $delimiter;
}
public function Convert($source) {
return \implode($this->delimiter, $source);
}
}
}
ImplodeConverter
期望输入为一个标量数组,并返回一个包含所有元素的连接字符串,如果指定了分隔符,则由分隔符分隔。
一个可能的例子是博客帖子中的类别或标签数组,应映射为一个单字符串,显示在帖子上方或下方。
IValueResolver
IValueResolver::Resolve()
方法期望源对象并返回目标属性解析后的值。
namespace Adminomatic\AutoMapper {
interface IValueResolver {
function Resolve($source);
}
}
值解析器示例(不包括在内)
有时目标属性的期望值取决于源对象的多个属性。你可以通过实现 IValueResolver
接口来创建任何需要的值解析器。
namespace MyNameSpace {
class FullNameResolver implements \Adminomatic\AutoMapper\IValueResolver {
function Resolve($source) {
if(!\is_object($source) || \get_class($source) != 'MyNameSpace\MyExpectedClass') {
return null;
}
return $source->FirstName . ' ' . $source->LastName;
}
}
}