w2w/apie-object-access-normalizer
Apie内部使用的Symfony规范器
Requires
- php: ^7.2
- phpdocumentor/reflection-docblock: ^4.3|5.*
- psr/cache: ^1.0
- symfony/http-kernel: ^4.3|^5.0
- symfony/property-info: ^4.3|^5.0
- symfony/serializer: ^4.3|^5.0
Requires (Dev)
- phpstan/phpstan: ^0.12.3
- phpunit/phpunit: ^8.5
- ramsey/uuid: ^3.8
- w2w/apie: ^3.2|dev-master|v4.x-dev
README
apie内部使用的对象访问规范器。它可以在symfony序列化器外部使用,可以替换那里使用的默认对象规范器。
与Symfony序列化器一起使用
最简单的用法是将ApieObjectAccessNormalizer添加到Symfony序列化器的构造函数中。
<?php use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; use Symfony\Component\Serializer\Serializer; use W2w\Lib\ApieObjectAccessNormalizer\Normalizers\ApieObjectAccessNormalizer; use W2w\Lib\ApieObjectAccessNormalizer\ObjectAccess\ObjectAccess; $serializer = new Serializer( [ new DateTimeNormalizer(), new ApieObjectAccessNormalizer(), new ArrayDenormalizer(), ], [new JsonEncoder()] ); class Example { private $number; private $stringValue = '<no value set>'; public function __construct(int $number) { $this->number = $number; } public function setStringValue(string $stringValue) { $this->stringValue = $stringValue; } public function getNumber(): int { return $this->number; } public function getStringValue(): string { return $this->stringValue; } } $instance = new Example(12); // returns array['number' => 12, 'stringValue' => '<no value set>'] var_dump($serializer->serialize($instance, 'json')); // returns new Example(12) var_dump($serializer->deserialize(['number' => 12], Example::class, 'json')); // throws validation error with errors => ['number' =>' must be one of "int" ("invalid" given)'] $serializer->deserialize(['number' => 'invalid'], Example::class, 'json'); // calls setStringValue("blah") on $instance $serializer->deserialize(['stringValue' => 'text'], Example::class, 'json', ['object_to_populate' => $instance]); // use a different object access on $instance to set private properties that have no public setter. $serializer->deserialize(['number' => '15'], Example::class, 'json', ['object_to_populate' => $instance, 'object_access' => new ObjectAccess(false)]);
除非调用上下文选项 'object_to_populate',否则它将首先尝试通过读取构造函数参数创建一个新对象。之后,它将检查所有setter。如果setter抛出错误,则错误被视为验证错误,并将返回一个包含错误结构的验证异常。
ObjectAccess还可以在PHP 7.4+中读取属性类型提示和php docblocks,使用composer包phpdocumentor/reflection-docblock。
驼峰式键
默认情况下,属性名称与键相同。我们可以在ApieObjectAccessNormalizer类中通过提供一个实现Symfony\Component\Serializer\NameConverter\NameConverterInterface的类来覆盖此设置。
<?php use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; use Symfony\Component\Serializer\Serializer; use W2w\Lib\ApieObjectAccessNormalizer\Normalizers\ApieObjectAccessNormalizer; use W2w\Lib\ApieObjectAccessNormalizer\ObjectAccess\ObjectAccess; $serializer = new Serializer( [ new DateTimeNormalizer(), new ApieObjectAccessNormalizer(new ObjectAccess(), new CamelCaseToSnakeCaseNameConverter()), new ArrayDenormalizer(), ], [new JsonEncoder()] ); $instance = new Example(12); // returns array['number' => 12, 'string_value' => '<no value set>'] var_dump($serializer->serialize($instance, 'json'));
高级用法
在许多情况下,您想要使用ObjectAccess,并且只想为特定类或接口使用不同的ObjectAccessInterface实现。为此,我们创建了GroupedObjectAccess。
<?php use Illuminate\Database\Eloquent\Model; use W2w\Laravel\LaravelApie\ObjectAccess\EloquentModelAccess; use W2w\Lib\ApieObjectAccessNormalizer\ObjectAccess\GroupedObjectAccess; use W2w\Lib\ApieObjectAccessNormalizer\ObjectAccess\ObjectAccess; use W2w\Lib\ApieObjectAccessNormalizer\ObjectAccess\SelfObjectAccess; use W2w\Lib\ApieObjectAccessNormalizer\ObjectAccess\SelfObjectAccessInterface; $objectAccess = new GroupedObjectAccess( new ObjectAccess, [ // For SomeClass we can read private properties/getters SomeClass::class => new ObjectAccess(false, true), // for any class that implements SelfobjectAccessInterface we use SelfObjectAccess SelfObjectAccessInterface::class => new SelfObjectAccess(), // does not exist in this package, just an example. Eloquent models are notorious for the amount of magic. Model::class => new EloquentModelObjectAccess(), ] );
可用的对象访问实现
- CachedObjectAccess:用于性能原因的缓存结果的装饰器。
- FilteredObjectAccess:筛选您可以实际使用的字段。另一个装饰器
- GroupedObjectAccess:请参阅高级用法。可以根据类使用不同的ObjectAcces实例
- ObjectAccess:默认对象访问。检查公共属性和公共setter和getter。
- SelfObjectAccess:适用于实现SelfObjectAccessInterface的类,因此类可以告诉自己它可以访问什么。
- LocalizationAwareObjectAccess:可用于具有本地化字段的对象。
本地化
从版本2开始,我们增加了本地化支持。在您的简单对象中添加如下setter,您就有了一个本地化字段
<?php namespace Wrwr; class ObjectWithLocalization { private $pizzas = []; public function setPizza(string $locale, string $preference) { $this->pizzas[$locale] = $preference; } public function getPizza(string $locale) { return $this->pizzas[$locale]; } }
这将生成一个支持本地化的字段 'pizza' 的setter和getter
在Symfony框架中
如果您想在Symfony框架中使用它,您只需将类W2w\Lib\ApieObjectAccessNormalizer\Normalizers\ApieObjectAccessNormalizer注册为服务,并使用'tags'将其标记为'serializer.normalizer'以将其添加到symfony序列化器即可。