【问题标题】:Callback argument in symfony service containersymfony 服务容器中的回调参数
【发布时间】: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();
});

但是,我似乎找不到将其添加到容器中的 &lt;call&gt; 的方法。

我已经研究过使用新的表达式引擎功能来尝试这个,但它似乎与回调不匹配。我还考虑过在某处添加独立功能并注册它是否可以使这项工作。现在我正在将方法调用入侵到我的序列化程序注入的类中。

我还尝试通过辅助 PHP 定义手动添加它:

$container->set(
    'tactic_monolith.entity_serializer_normalizer_circular_reference_handler',
    function ($object) {
        return $object->getId();
    }
);

但它似乎被默默地忽略了。在执行 setParameter 时,我收到一个错误(可调用对象不能是参数)。我也尝试将其注册为综合服务。

【问题讨论】:

  • 您只需要使用 setCircularReferenceHandler 来摆脱 CircularReferenceError 吗?而且你没有用 serializer.normalizer 标记你的规范化器,那么你的序列化器怎么知道他必须使用这个 ObjectSerializer 而不是默认的呢?
  • 正确,setCircularReferenceHandler 只是为了防止抓取我的循环引用。我用这个规范器和$this-&gt;get('my.custom_serializer') 创建了一个序列化器服务定义。
  • Symfony Serializer 分两步提供序列化:规范化(例如使用像 CustomObjectNormalizer 或 ObjectNormalizer 这样的规范化器)和 编码(使用编码器)。在您想要自定义规范化过程的情况下,您不需要自定义整个序列化程序。创建一个自定义对象规范化器,用 serializer.normalizer 对其进行标记,然后简单地使用您的序列化器 $this-&gt;get('serializer') 。序列化程序将自动使用您的自定义规范化程序。
  • 这很有趣,你的意思是像这样他们实现了 UserNormalizer thomas.jarrand.fr/blog/serialization 吗?我不知道我是否会使用该标签,因为我不确定我是否希望它改变我的serializer 服务在任何地方的行为。
  • 是这样的。在您向我展示的文章中,查找此“您的域逻辑位于规范器中”。这就是我所说的。您可以根据需要创建规范化程序并使用默认序列化程序声明它们。最终的目标是什么?需要时使用正确的归一化器。是否使用 symfony 框架提供的这种方法,由你自己决定

标签: php dependency-injection symfony inversion-of-control


【解决方案1】:

似乎不使用工厂就无法做到这一点。

class CircularHandlerFactory
{
    public static function getId(){
        return (function ($object) {
            return $object->getId();
        });
    }
}

<service
    id="some_bundle.circular_reference_handler"
    class="callback"
>
    <factory class="SomeBundle\CircularHandlerFactory" method="getId" />
</service>

最后添加对规范器的调用:

<call method="setCircularReferenceHandler">
    <argument type="service" id="some_bundle.circular_reference_handler"/>
</call>

事后看来,这可能是对该功能的不当使用。但是,这对于表达式引擎的功能请求来说也可能是值得的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 2016-02-16
    • 1970-01-01
    相关资源
    最近更新 更多