【发布时间】:2017-03-05 23:49:47
【问题描述】:
我正在使用 Symfony 的注入容器和 Serializer 组件来提供每次使用默认序列化配置的服务。具体使用 ObjectNormalizer:
<service
id="my_bundle.entity_serializer_normalizer"
class="Symfony\Component\Serializer\Normalizer\ObjectNormalizer"
>
<argument type="service" id="my_bundle.entity_serializer_normalizer_metadata_factory" />
<argument>null</argument>
<argument>null</argument>
<argument type="service" id="my_bundle.entity_serializer_normalizer_reflection_extractor" />
<call method="setIgnoredAttributes">
<argument type="collection">
<argument>__initializer__</argument>
<argument>__cloner__</argument>
<argument>__isInitialized__</argument>
</argument>
</call>
</service>
但是,我还需要调用此服务上的一个方法来设置循环引用处理程序。在常规 PHP 中,这看起来像这样:
$normalizer->setCircularReferenceHandler(function ($object) {
return $object->getId();
});
但是,我似乎找不到将其添加到容器中的 <call> 的方法。
我已经研究过使用新的表达式引擎功能来尝试这个,但它似乎与回调不匹配。我还考虑过在某处添加独立功能并注册它是否可以使这项工作。现在我正在将方法调用入侵到我的序列化程序注入的类中。
我还尝试通过辅助 PHP 定义手动添加它:
$container->set(
'tactic_monolith.entity_serializer_normalizer_circular_reference_handler',
function ($object) {
return $object->getId();
}
);
但它似乎被默默地忽略了。在执行 setParameter 时,我收到一个错误(可调用对象不能是参数)。我也尝试将其注册为综合服务。
【问题讨论】:
-
您只需要使用 setCircularReferenceHandler 来摆脱 CircularReferenceError 吗?而且你没有用 serializer.normalizer 标记你的规范化器,那么你的序列化器怎么知道他必须使用这个 ObjectSerializer 而不是默认的呢?
-
正确,
setCircularReferenceHandler只是为了防止抓取我的循环引用。我用这个规范器和$this->get('my.custom_serializer')创建了一个序列化器服务定义。 -
Symfony Serializer 分两步提供序列化:规范化(例如使用像 CustomObjectNormalizer 或 ObjectNormalizer 这样的规范化器)和 编码(使用编码器)。在您想要自定义规范化过程的情况下,您不需要自定义整个序列化程序。创建一个自定义对象规范化器,用 serializer.normalizer 对其进行标记,然后简单地使用您的序列化器
$this->get('serializer')。序列化程序将自动使用您的自定义规范化程序。 -
这很有趣,你的意思是像这样他们实现了
UserNormalizerthomas.jarrand.fr/blog/serialization 吗?我不知道我是否会使用该标签,因为我不确定我是否希望它改变我的serializer服务在任何地方的行为。 -
是这样的。在您向我展示的文章中,查找此“您的域逻辑位于规范器中”。这就是我所说的。您可以根据需要创建规范化程序并使用默认序列化程序声明它们。最终的目标是什么?需要时使用正确的归一化器。是否使用 symfony 框架提供的这种方法,由你自己决定
标签: php dependency-injection symfony inversion-of-control