Symfony 4.2自定义循环引用处理程序不适用

时间:2019-04-12 16:25:47

标签: config normalization circular-reference symfony-4.2

上下文是,我一直在尝试为将影响所有实体的实体设置自定义循环引用处理程序。

根据文档(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

为什么我的替代项根本没有应用于上下文?

我试图:

  • 重新加载缓存
  • 使用我的API平台软件包中的ContextBuilder类
  • 在规范化器中应用

没有一个工作

我向您展示了我的yaml,但这是处理程序:

<?php

namespace App\Services;

class CircularReferenceHandler
{
    /**
     * @param object $object
     * @return mixed
     */
    public function __invoke($object)
    {
        return $object->getId();
    }
}

这是我尝试用作替代方法的“上下文”构建器:

<?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()方法时将应用我的自定义circle_reference_handler,但实际情况是此方法中接收到的上下文不包括其他键/值对(例如['circular_reference_handler => App\Services\CircularReferenceHandler]

1 个答案:

答案 0 :(得分:0)

因此,我发现使用Normalizer策略时一定犯了一个错误。本质上,如果要全局更改序列化器$context(SerializerInterface-> serialize($ data,$ format, array $ context = [] )),那么您应该创建一个自定义的 Symfony 规范化器。

这是我的最后一堂课:

<?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()。到目前为止,这是我唯一需要进行更改的地方,并且该接口要求我至少残存其余方法,以便您可以忽略其他方法。但是,现在我有了一个地方,可以在需要时全局更改序列化上下文的数据或状态。

希望这对其他人有帮助。