0

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

根据文档(https://symfony.com/doc/current/components/serializer.html#handling-circular-references),我们被引导在文件中设置服务circular_reference_handler下的值,如下所示:serializerconfig/packages/framework.yaml

framework:
    validation:
        enabled: true

    messenger:
        enabled: true

    assets:
        enabled: true

    serializer:
        circular_reference_handler: App\Services\CircularReferenceHandler
        enable_annotations: true

我的实际问题是,当序列化程序尝试加载循环引用处理程序时,我的覆盖似乎不存在: 图像显示键引用 图像显示上下文为空

为什么我的覆盖根本没有应用于上下文?

我试图:

  • 重新加载缓存
  • 使用我的 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()在使用该方法时应用我的自定义 circular_reference_handler ,但实际情况是此方法中收到的上下文不包括我的附加键/值对(例如['circular_reference_handler => App\Services\CircularReferenceHandler]

4

1 回答 1

2

所以我发现我在使用 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()。到目前为止,这是我唯一需要进行更改的地方,并且界面要求我至少将其余方法存根,这样您就可以忽略其他方法。但是,现在我有一个地方可以在需要时全局更改序列化上下文的数据或状态。

希望这对其他人有帮助。

于 2019-04-12T18:50:48.870 回答