上下文是我一直在尝试为我的实体设置一个自定义循环引用处理程序,它将影响所有实体。
根据文档(https://symfony.com/doc/current/components/serializer.html#handling-circular-references),我们被引导在circular_reference_handler
文件中的serializer
服务下设置config/packages/framework.yaml
值:
framework:
validation:
enabled: true
messenger:
enabled: true
assets:
enabled: true
serializer:
circular_reference_handler: App\Services\CircularReferenceHandler
enable_annotations: true
我的实际问题是,当序列化程序尝试加载循环引用处理程序时,我的覆盖似乎不存在:image showing key referenced image showing context empty
为什么我的覆盖不能应用于上下文?
我试图:
没有工作过
我告诉你我的yaml,但这是处理程序:
<?php
namespace App\Services;
class CircularReferenceHandler
{
/**
* @param object $object
* @return mixed
*/
public function __invoke($object)
{
return $object->getId();
}
}
这是我试图用作替代的Context构建器:
<?php
namespace App\Serializer;
use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface;
use App\Services\CircularReferenceHandler;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
final class GlobalSerializerContextBuilder implements SerializerContextBuilderInterface
{
/**
* Creates a serialization context from a Request.
*
* @param Request $request
* @param bool $normalization
* @param array|null $extractedAttributes
*
* @return array
*/
public function createFromRequest(Request $request, bool $normalization, array $extractedAttributes = null): array
{
$resourceClass = $context['resource_class'] ?? null;
$context[AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER] = CircularReferenceHandler::class;
return $context;
}
}
这是我注册的地方(doc):
App\Serializer\GlobalSerializerContextBuilder:
decorates: 'api_platform.serializer.context_builder'
arguments: ['@App\Serializer\GlobalSerializerContextBuilder.inner']
autoconfigure: false
我期望在使用AbstractNormalizer->handleCircularReference()
方法时应用我的自定义circular_reference_handler,但实际情况是此方法中收到的上下文不包括我的附加键/值对(例如['circular_reference_handler => App\Services\CircularReferenceHandler]
)
所以我发现在使用Normalizer策略时我肯定犯了一个错误。基本上,如果你想全局更改序列化程序$context
(SerializerInterface-> serialize中的第三个参数($ data,$ format,array $ context = [])),那么你应该创建一个自定义的Symfony Normalizer。
这是我的最后一堂课:
<?php
namespace App\Serializer;
use App\Services\CircularReferenceHandler;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
/**
* Class ApiNormalizer. Acts as an entrypoint to GLOBALLY alter context for all denormalizers and normalizers ( and subsequenty the serializers ).
* @package App\Serializer
*/
final class ApiNormalizer implements NormalizerInterface, DenormalizerInterface
{
private $normalizer;
public function __construct(NormalizerInterface $normalizer)
{
if (!$normalizer instanceof DenormalizerInterface) {
throw new \InvalidArgumentException('The normalizer must implement the DenormalizerInterface');
}
$this->normalizer = $normalizer;
}
public function denormalize($data, $class, $format = null, array $context = [])
{
return $this->normalizer->denormalize($data, $class, $format, $context);
}
public function supportsDenormalization($data, $type, $format = null)
{
return $this->normalizer->supportsDenormalization($data, $type, $format);
}
public function normalize($object, $format = null, array $context = [])
{
$context[AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER] = CircularReferenceHandler::class;
$context['enable_max_depth'] = true;
return $this->normalizer->normalize($object, $format, $context);
}
public function supportsNormalization($data, $format = null)
{
return $this->normalizer->supportsNormalization($data, $format);
}
}
看的方法只是normalize()
。这是我现在需要进行更改的唯一地方,并且接口要求我至少将其余的方法存根,以便您可以忽略其他方法。但是,现在我有一个地方可以在需要时全局更改序列化上下文的数据或状态。
希望这有助于其他人。