peekandpoke / slumber
通过注解进行序列化
Requires
- php: >=7.1
- doctrine/common: ^2.8.1
- peekandpoke/php-types: ~1.2.0
- peekandpoke/psi: ^1.0.1
- psr/container: ^1.0
- psr/log: ^1.0.2
- symfony/finder: ^3.3.10
Requires (Dev)
- phpunit/phpunit: ^7.0.1
- roave/security-advisories: dev-master
README
Slumber
什么是Slumber?它是一个将对象数据映射到数组以及反向映射的工具。
它允许您轻松地将领域模型映射到JSON。或者将JSON映射到领域模型类。
Slumber使用Doctrine注解。注解用于标记哪些类的属性需要映射以及如何映射。
(PHP5.6兼容性直到v0.4.x)
基本示例
Slumber注解类的“标志”是这些注解
use PeekAndPoke\Component\Slumber\Annotation\Slumber; class MyClass { /** * @Slumber\AsString() */ private $name; /** * @Slumber\AsInteger() */ private $age; /** * @Slumber\AsDecimal() */ private $height; /** * @Slumber\AsObject(Address::class) */ private $address; } echo json_encode($codec->slumber(new MyClass());
可能输出以下内容
{
"name": "Bart",
"age": 10,
"height": 1.10,
"address": {
"city": "Springfield",
"country": "USA"
}
}
入门指南
数组编解码器示例
为了获得数组编解码器,我们需要设置它
// we need an instance of a PSR-11 container (should be provided by the application) $di = ...; // we need a doctrine annotation reader (you should use caching, ideally APCU as cache) $annotationReader = new AnnotationReader(); // SLUMBER: we need a configuration reader (you should wrap the reader with CachedEntityConfigLookUp for good performance) $reader = new AnnotatedEntityConfigReader($di, $annotationReader, new ArrayCodecPropertyMarker2Mapper()); // SLUMBER: finally we get the codec $codec = new ArrayCodec($reader); // then use it for serializating objects into array data $data = $codec->slumber(new Person()); // or use if for de-serializating array data back into objects $person = $codec->awake($data, Person::class);
映射
为了完全控制序列化和反序列化,有一组可以使用的注解。
映射标量
您可以在这里找到所有映射器的实现
Slumber\AsBool()
映射值到布尔值。
class C { /** * @Slumber\AsBool() */ private $val = true; }
映射到
{
"val": true
}
class C { /** * @Slumber\AsBool() */ private $val = 0; }
映射到
{
"val": false
}
相反方向的行为相同。有关映射器如何工作的更多详细信息,请参阅这里
Slumber\AsDecimal()
映射值到浮点值。
class C { /** * @Slumber\AsDecimal() */ private $val = 1.23; }
映射到
{
"val": 1.23
}
class C { /** * @Slumber\AsDecimal() */ private $val = "abc"; }
映射到
{
"val": 0
}
相反方向的行为相同。有关映射器如何工作的更多详细信息,请参阅这里
Slumber\AsInteger()
映射值到浮点值。
class C { /** * @Slumber\AsInteger() */ private $val = 1.23; }
映射到
{
"val": 1
}
class C { /** * @Slumber\AsInteger() */ private $val = "abc"; }
映射到
{
"val": 0
}
相反方向的行为相同。有关映射器如何工作的更多详细信息,请参阅这里
Slumber\AsIs()
映射值保持不变。
class C { /** * @Slumber\AsAs() */ private $val = 1.23; }
映射到
{
"val": 1.23
}
class C { /** * @Slumber\AsIs() */ private $val = "abc"; }
映射到
{
"val": "abc"
}
相反方向的行为相同。有关映射器如何工作的更多详细信息,请参阅这里
Slumber\AsString()
映射值到浮点值。
class C { /** * @Slumber\AsString() */ private $val = 1.23; }
映射到
{
"val": "1.23"
}
class C { /** * @Slumber\AsString() */ private $val = "abc"; }
映射到
{
"val": "abc"
}
相反方向的行为相同。有关映射器如何工作的更多详细信息,请参阅这里
映射嵌套对象
Slumber\AsObject()
映射到和从嵌套对象。
class B { /** * @Slumber\AsString() */ private $name; } class C { /** * @Slumber\AsObject(B::class) */ private $val = new B(); // syntax error ... new B() only for demonstration purposes }
映射到
{
"val": {
"name": "..."
}
}
class C { /** * @Slumber\AsString() */ private $val = "abc"; }
映射到
{
"val": null
}
相反方向的行为相同。有关映射器如何工作的更多详细信息,请参阅这里
Slumber\AsEnum()
映射值到枚举值。
为此,我们需要一个枚举类。有关枚举的详细信息,请参阅这里。
class Enum extends Enumerated { /** @var Enum */ public static $ONE; /** @var Enum */ public static $TWO; } Enum::init();
class C { /** * @Slumber\AsEnum(Enum::class) */ private $val = Enum::$ONE; }
映射到
{
"val": "ONE"
}
class C { /** * @Slumber\AsEnum(Enum::class) */ private $val = "abc"; }
映射到
{
"val": null
}
相反方向的行为相同。有关映射器如何工作的更多详细信息,请参阅这里
映射集合、列表、键值对
Slumber\AsList()
映射值到列表(无索引的数组)。
注解期望嵌套注解来控制集合内元素的形状。
class C { /** * @Slumber\AsList( * @Slumber\AsDecimal() * ) */ private $val = [1.1, 2.2, 3.3]; }
映射到
{
"val": [1.1, 2.2, 3.3]
}
class C { /** * @Slumber\AsList( * @Slumber\AsDecimal() * ) */ private $val = ["a": 1.1, "b": 2.2, "c": 3.3]; }
映射到
{
"val": [1.1, 2.2, 3.3]
}
相同的行为也适用于相反方向。有关映射器的工作原理的更多详细信息,请查看此处
类似地,可以将映射到对象列表
class B { } class C { /** * @Slumber\AsList( * @Slumber\AsObject(B::Class) * ) */ private $val = []; }
Slumber\AsMap()
从和到键值对(索引数组)映射值。
注解期望嵌套注解来控制集合内元素的形状。
class C { /** * @Slumber\AsMap( * @Slumber\AsDecimal() * ) */ private $val = [1.1, 2.2, 3.3]; }
映射到
{
"val": { "0": 1.1, "1": 2.2, "2": 3.3 }
}
class C { /** * @Slumber\AsList( * @Slumber\AsDecimal() * ) */ private $val = ["a": 1.1, "b": 2.2, "c": 3.3]; }
映射到
{
"val": { "a": 1.1, "b": 2.2, "c": 3.3}
}
相同的行为也适用于相反方向。有关映射器的工作原理的更多详细信息,请查看此处
类似地,可以将映射到对象列表
class B { } class C { /** * @Slumber\AsMap( * @Slumber\AsObject(B::Class) * ) */ private $val = []; }
Slumber\AsKeyValuePairs()
从和到特殊形状的键值对映射值。这在数据库索引方面可能很有用。
注解期望嵌套注解来控制集合内元素的形状。
class C { /** * @Slumber\AsMap( * @Slumber\AsDecimal() * ) */ private $val = [1.1, 2.2, 3.3]; }
映射到
{
"val": [
{ "k": "0", "v": 1.1 },
{ "k": "1", "v": 2.2 },
{ "k": "2", "v": 3.3 }
]
}
class C { /** * @Slumber\AsList( * @Slumber\AsDecimal() * ) */ private $val = ["a": 1.1, "b": 2.2, "c": 3.3]; }
映射到
{
"val": [
{ "k": "a", "v": 1.1 },
{ "k": "b", "v": 2.2 },
{ "k": "c", "v": 3.3 }
]
}
相同的行为也适用于相反方向。有关映射器的工作原理的更多详细信息,请查看此处
类似地,可以将映射到对象列表
class B { } class C { /** * @Slumber\AsKeyValuePairs( * @Slumber\AsObject(B::Class) * ) */ private $val = []; }
多态示例
在序列化时不需要多态信息。因为我们知道我们手中确切的类将被序列化。
但在反序列化时,必须显式注释多态。只有通过这样做,我们才能知道要实例化的类。我们还需要在数据中有一个字段,该字段充当判别器。
use PeekAndPoke\Component\Slumber\Annotation\Slumber; /* * @Slumber\Polymorphic( * { * "adyen" : Adyen::class, * "paypal" : Paypal::class, * "stripe" : Stripe::class, * }, * tellBy = "provider", * default = PaymentMean::class * ) */ class PaymentMean { /** * The discriminator field * * @Slumber\AsString() */ private $provider; /* ... */ } class Adyen extends PaymentMean { /* ... */ } class Paypal extends PaymentMean { /* ... */ } class Stripe extends PaymentMean { /* ... */ }
票据
下一个票据编号:14
优先级 I
SLUMBER-13 - 0%
( ) 单元测试用于多态性回退到默认
( ) a) 判别器未设置
( ) b) 设置了未知判别器
SLUMBER-12 - 50% - 实现存储在单个集合中的多个类型时的别名类 -> 为了在单个集合中存储多个类型,我们必须能够指定存储库的别名类 (x) 报告于 2016-11-15 (x) 实现 2016-11-15 ( ) 单元测试
SLUMBER-4 - 0% - 将 MongoDbCodec 中的硬编码访问者重构为来自 MongoDbEntityConfig -> 配置读取器必须自动添加访问者 (用户能否以某种方式覆盖这些?) -> 这更通用,并且与用户附加的监听器配合使用时将正常工作 (x) 报告于 2016-05-01
(x) 报告于 2016-05-01
SLUMBER-7 - 0% -
优先级 II
SLUMBER-3 - 0% - 允许 onPreCreate() 等访问者传递事件类而不是多个参数 -> 更好的可扩展性 -> 事件传播可以停止 (x) 报告于 2016-05-01
SLUMBER-2 - 0% - 首先设置和通过获取器和设置器读取属性。如果不可能,则使用反射
-> 读取和写入继承的私有属性将变得可能
-> +33% 速度
(x) 报告于 2016-05-01
SLUMBER-8 - 0% - 为 Data\MongoDB 实现GeoJSON支持
-> 实现 GeoSpatialIndex 以支持 GeoJson 类型 -> 实现 GeoJsonPolygon、GeoJsonMultiPolygon 和其他 GeoJson 类型 (x) 报告于 2016-05-12
SLUMBER-7 - IRepository::save 应该返回比 @return array|null 更具体的结果 (x) 报告于 2016-05-12
优先级 III
SLUMBER-6 - 0% - 将 Slumber\Swagger 建立为自己的包,并基于通用代码生成组件 -> 这是一个自己的项目 -> 移除 gossi/php-code-gen (x) 报告于 2016-05-01
已完成
SLUMBER-1 - 100% - 删除 @AsOne2One 注解,并像 @AsId 一样执行类似操作 -> 当前标记为这样的实体不能与 ArrayCodec 一起使用(这是有问题的行为) (x) 完成 2016-05-11
SLUMBER-5 - 100% - 将 Slumber\MongoDb 移动到 Slumber\Data\MongoDb -> Slumber\Data 将是所有数据库事物的家 (x) 完成 2016-05-11
SLUMBER-9 - 100% - 实现多态的休眠和唤醒 (x) 报告于 2016-05-14 (x) 完成 2016-10-01 (x) 单元测试
SLUMBER-10 - 100% 实现所有 AsCollection 映射的集合类的使用 -> 这将使将传入的数组包装到集合类中成为可能。 -> 这将增加对数组操作的可方便性,因为代码将与数据封装在一起 -> 示例:包含标签的 TagsSet 集合类型可以具有 has()、addUnique()、remove() 等方法 (x) 报告于 2016-11-01 (x) 完成 2016-11-13 (x) 单元测试
SLUMBER-11 - 100%实现了LazyDbRefCollection以存储引用对象的列表(x)报告日期2016-11-13(x)完成日期2016-11-13(x)单元测试