symfonyapi平台下MongoDb嵌入式文档的反规范化
我正在尝试使用API平台捆绑包在带有Symfony 4.4的嵌入式MongoDB文档上运行反规范化程序(data in)。这与规范化(数据输出)的预期效果一样,但对于非规范化过程,不会对嵌入数据触发任何操作,只对父数据触发任何操作 如果这是它的工作方式,那么我可能需要将反规范化的逻辑移到父级。或许我只是做错了什么。我试图完成的是对包含已弃用字段的入站请求抛出异常。解析注释和扫描属性的类按预期工作,它只是确定在哪里插入它,我希望嵌入文档上的非规范化过程能够工作 这是我的服务。yaml:symfonyapi平台下MongoDb嵌入式文档的反规范化,symfony,symfony4,api-platform.com,Symfony,Symfony4,Api Platform.com,我正在尝试使用API平台捆绑包在带有Symfony 4.4的嵌入式MongoDB文档上运行反规范化程序(data in)。这与规范化(数据输出)的预期效果一样,但对于非规范化过程,不会对嵌入数据触发任何操作,只对父数据触发任何操作 如果这是它的工作方式,那么我可能需要将反规范化的逻辑移到父级。或许我只是做错了什么。我试图完成的是对包含已弃用字段的入站请求抛出异常。解析注释和扫描属性的类按预期工作,它只是确定在哪里插入它,我希望嵌入文档上的非规范化过程能够工作 这是我的服务。yaml: 'App\
'App\Serializer\InvestmentNormalizer':
arguments: [ '@security.authorization_checker' ]
tags:
- { name: 'serializer.normalizer', priority: 64 }
'App\Serializer\InvestmentDenormalizer':
tags:
- { name: 'serializer.denormalizer', priority: 64 }
'App\Serializer\ProjectNormalizer':
tags:
- { name: 'serializer.normalizer', priority: 64 }
'App\Serializer\ProjectDenormalizer':
tags:
- { name: 'serializer.denormalizer', priority: 64 }
然后我的反规范化器类永远不会执行:
class ProjectDenormalizer implements DenormalizerInterface
{
private const ALREADY_CALLED = 'PROJECT_DENORMALIZER_ALREADY_CALLED';
public function denormalize($data, $class, $format = null, array $context = [])
{
$context[self::ALREADY_CALLED] = true;
return $this->removeDeprecatedFields($data);
}
public function supportsDenormalization($data, $type, $format = null)
{
if (isset($context[self::ALREADY_CALLED])) {
return false;
}
return $type == get_class(new Project());
}
private function removeDeprecatedFields(array $normalizedData) : array
{
$apiPropertyReader = new AnnotationReader(Project::class, ApiProperty::class);
$deprecatedProperties = $apiPropertyReader->readAllHavingAttribute('deprecationReason');
$errors = [];
foreach (array_keys($deprecatedProperties) as $deprecatedPropertyName) {
if (!isset($normalizedData[$deprecatedPropertyName])) {
continue;
}
$errors[] = $deprecatedPropertyName . ' has been deprecated';
}
if (!empty($errors)) {
throw new DeprecatedFieldException(implode('. ', $errors));
}
return $normalizedData;
}
}
如果您查看文档,您会发现序列化程序组件没有任何
序列化程序。反规范化程序服务,
因此,自动发现不会检测到您的类
您需要遵循并实现Normalizer,它在单个类中实现Normalizer和denormalizer逻辑,并将其注册为Normalizer
然后名称约定听起来很混乱,但是如果您的规范化程序有反规范化接口
,那么它负责反规范化,如果它有规范化接口
,那么它负责非规范化,通过将序列化逻辑标记到适当的方法,它们将被相应地调用
API平台it自身有关于两者如何工作的示例:
下面是如何在api平台中修饰normalizer:
api/config/services.yaml
或者您可以按照symfony方式注册此规范化器:
config/services.yaml
实施:
namespace App\Serializer;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\SerializerAwareInterface;
use Symfony\Component\Serializer\SerializerInterface;
final class ApiNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface
{
private $decorated;
public function __construct(NormalizerInterface $decorated)
{
if (!$decorated instanceof DenormalizerInterface) {
throw new \InvalidArgumentException(sprintf('The decorated normalizer must implement the %s.', DenormalizerInterface::class));
}
$this->decorated = $decorated;
}
public function supportsNormalization($data, $format = null)
{
return $this->decorated->supportsNormalization($data, $format);
}
public function normalize($object, $format = null, array $context = [])
{
$data = $this->decorated->normalize($object, $format, $context);
if (is_array($data)) {
$data['date'] = date(\DateTime::RFC3339);
}
return $data;
}
public function supportsDenormalization($data, $type, $format = null)
{
return $this->decorated->supportsDenormalization($data, $type, $format);
}
public function denormalize($data, $class, $format = null, array $context = [])
{
return $this->decorated->denormalize($data, $class, $format, $context);
}
public function setSerializer(SerializerInterface $serializer)
{
if($this->decorated instanceof SerializerAwareInterface) {
$this->decorated->setSerializer($serializer);
}
}
}
您可以折射逻辑并为每个实体创建规范化器类。不管您使用什么数据库,对于PHP和Symfony,它都是对象
在这里浏览完整的文档以了解它是如何实现的:API平台选择的命名约定非常混乱,奇怪的是我无法通过分离流程来遵循可靠的实践。我回到办公室后会试试这个。谢谢。事实上,它本质上是实现规范化、非规范化接口的数据转换器类。服务标记将检查它是否是其中一个的实例,并调用相应的方法。您可以尝试注册seprate类以进行反规范化,它应该可以正常工作,只需使用适当的标记,即可被序列化程序捕获。因此,如果在单独的类中尝试,也可以将其标记为反规范化程序?我还没有时间使用api平台对其进行测试,理论上它应该可以工作,symfony希望使用NormalizerInterface实例,使用正确实现的序列化程序(api平台的api_platform.jsonld.normalizer.item)反规范化接口。
services:
get_set_method_normalizer:
class: Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer
tags: [serializer.normalizer]
namespace App\Serializer;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\SerializerAwareInterface;
use Symfony\Component\Serializer\SerializerInterface;
final class ApiNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface
{
private $decorated;
public function __construct(NormalizerInterface $decorated)
{
if (!$decorated instanceof DenormalizerInterface) {
throw new \InvalidArgumentException(sprintf('The decorated normalizer must implement the %s.', DenormalizerInterface::class));
}
$this->decorated = $decorated;
}
public function supportsNormalization($data, $format = null)
{
return $this->decorated->supportsNormalization($data, $format);
}
public function normalize($object, $format = null, array $context = [])
{
$data = $this->decorated->normalize($object, $format, $context);
if (is_array($data)) {
$data['date'] = date(\DateTime::RFC3339);
}
return $data;
}
public function supportsDenormalization($data, $type, $format = null)
{
return $this->decorated->supportsDenormalization($data, $type, $format);
}
public function denormalize($data, $class, $format = null, array $context = [])
{
return $this->decorated->denormalize($data, $class, $format, $context);
}
public function setSerializer(SerializerInterface $serializer)
{
if($this->decorated instanceof SerializerAwareInterface) {
$this->decorated->setSerializer($serializer);
}
}
}