ObjectNormalizer 覆盖 RelationshipNormalizer 导致代码崩溃,为什么?
ObjectNormalizer overrides RelationshipNormalizer causing code to crash, why?
我正在尝试添加我自己的规范化器,因为我需要将一些原始值转换(非规范化)到它的相关实体。这就是我所做的:
namespace MMI\IntegrationBundle\Serializer\Normalizer;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
class RelationshipNormalizer implements NormalizerInterface, DenormalizerInterface
{
public function normalize($object, $format = null, array $context = [])
{
// @TODO implement this method
}
public function supportsNormalization($data, $format = null): bool
{
return $data instanceof \AgreementType;
}
public function denormalize($data, $class, $format = null, array $context = [])
{
// @TODO implement this method
}
public function supportsDenormalization($data, $type, $format = null): bool
{
$supportedTypes = [
\AgreementType::class => true
];
return isset($supportedTypes[$type]);
}
}
这就是我在控制器中使用它的方式:
$propertyNameConverter = new PropertyNameConverter();
$encoder = new JsonEncoder();
$normalizer = new ObjectNormalizer(
null,
$propertyNameConverter,
null,
new ReflectionExtractor()
);
$serializer = new Serializer([
new DateTimeNormalizer(),
new RelationshipNormalizer(),
$normalizer,
new ArrayDenormalizer(),
], [$encoder]);
当代码到达this method时:
private function getNormalizer($data, $format, array $context)
{
foreach ($this->normalizers as $normalizer) {
if ($normalizer instanceof NormalizerInterface && $normalizer->supportsNormalization($data, $format, $context)) {
return $normalizer;
}
}
}
使用 Xdebug 和 IDE 我可以看到条件 $data instanceof \AgreementType
是如何完成的,但是代码再次尝试检查 Normalizer 然后 this function 被执行:
public function supportsDenormalization($data, $type, $format = null)
{
return class_exists($type);
}
这正是我使用错误的规范化器导致以下错误的地方:
Notice: Uninitialized string offset: 0 in
vendor/symfony/symfony/src/Symfony/Component/Inflector/Inflector.php
at line 179
更新:
我已经尝试过这种其他方式,结果与之前完全相同,意思是相同的错误消息:
$callback = function ($value) {
$value = $this->em->getRepository('QuoteBundle:' . $this->table_mapping[$this->entity])->find($value);
return $value;
};
$entityNormalizer = new GetSetMethodNormalizer();
$entityNormalizer->setCallbacks([
'agreementType' => $callback,
]);
$serializer = new Serializer([
new DateTimeNormalizer(),
$normalizer,
$entityNormalizer,
new ArrayDenormalizer(),
], [$encoder]);
我在这里缺少什么?
在 Slack 上的#symfony-devs 频道获得一些帮助后,我确实发现顺序很重要。这是我的问题的解决方案(将下面的代码片段与 OP 上的代码片段进行比较,您会看到不同之处):
$normalizer = new ObjectNormalizer(
null,
$propertyNameConverter,
null,
new ReflectionExtractor()
);
// Notice how ObjectNormalizer() is the last normalizer
$serializer = new Serializer([
new ArrayDenormalizer(),
new DateTimeNormalizer(),
new RelationshipNormalizer($em),
$normalizer,
], [$encoder]);
我正在尝试添加我自己的规范化器,因为我需要将一些原始值转换(非规范化)到它的相关实体。这就是我所做的:
namespace MMI\IntegrationBundle\Serializer\Normalizer;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
class RelationshipNormalizer implements NormalizerInterface, DenormalizerInterface
{
public function normalize($object, $format = null, array $context = [])
{
// @TODO implement this method
}
public function supportsNormalization($data, $format = null): bool
{
return $data instanceof \AgreementType;
}
public function denormalize($data, $class, $format = null, array $context = [])
{
// @TODO implement this method
}
public function supportsDenormalization($data, $type, $format = null): bool
{
$supportedTypes = [
\AgreementType::class => true
];
return isset($supportedTypes[$type]);
}
}
这就是我在控制器中使用它的方式:
$propertyNameConverter = new PropertyNameConverter();
$encoder = new JsonEncoder();
$normalizer = new ObjectNormalizer(
null,
$propertyNameConverter,
null,
new ReflectionExtractor()
);
$serializer = new Serializer([
new DateTimeNormalizer(),
new RelationshipNormalizer(),
$normalizer,
new ArrayDenormalizer(),
], [$encoder]);
当代码到达this method时:
private function getNormalizer($data, $format, array $context)
{
foreach ($this->normalizers as $normalizer) {
if ($normalizer instanceof NormalizerInterface && $normalizer->supportsNormalization($data, $format, $context)) {
return $normalizer;
}
}
}
使用 Xdebug 和 IDE 我可以看到条件 $data instanceof \AgreementType
是如何完成的,但是代码再次尝试检查 Normalizer 然后 this function 被执行:
public function supportsDenormalization($data, $type, $format = null)
{
return class_exists($type);
}
这正是我使用错误的规范化器导致以下错误的地方:
Notice: Uninitialized string offset: 0 in vendor/symfony/symfony/src/Symfony/Component/Inflector/Inflector.php at line 179
更新:
我已经尝试过这种其他方式,结果与之前完全相同,意思是相同的错误消息:
$callback = function ($value) {
$value = $this->em->getRepository('QuoteBundle:' . $this->table_mapping[$this->entity])->find($value);
return $value;
};
$entityNormalizer = new GetSetMethodNormalizer();
$entityNormalizer->setCallbacks([
'agreementType' => $callback,
]);
$serializer = new Serializer([
new DateTimeNormalizer(),
$normalizer,
$entityNormalizer,
new ArrayDenormalizer(),
], [$encoder]);
我在这里缺少什么?
在 Slack 上的#symfony-devs 频道获得一些帮助后,我确实发现顺序很重要。这是我的问题的解决方案(将下面的代码片段与 OP 上的代码片段进行比较,您会看到不同之处):
$normalizer = new ObjectNormalizer(
null,
$propertyNameConverter,
null,
new ReflectionExtractor()
);
// Notice how ObjectNormalizer() is the last normalizer
$serializer = new Serializer([
new ArrayDenormalizer(),
new DateTimeNormalizer(),
new RelationshipNormalizer($em),
$normalizer,
], [$encoder]);