symfony - Doctrine 2 : disable lazy loading/proxy generation.

标签 symfony doctrine-orm doctrine jmsserializerbundle jms-serializer

使用 Doctrine 2,是否有可能:

  • 从生成的代理类中排除属性?
  • 完全禁用延迟加载/代理生成?

  • 我在序列化我的实体时遇到问题(使用 Symfony 和 JMS Serializer)。我只想序列化我在查询中明确获取的关联实体。

    f.e. 中描述的解决方案Disable Doctrine 2 lazy loading when using JMS Serializer?只是部分工作。当您拥有虚拟属性(property)时:
    use Doctrine\ORM\Mapping as ORM;
    use JMS\Serializer\Annotation as Serializer;
    
    /**
     * Profile
     *
     * @ORM\Table(name="profile")
     * @ORM\Entity
     */
    class Profile
    {
        // ...
    
        /**
         * @return string
         *
         * @Serializer\VirtualProperty()
         */
        public function getLabel()
        {
            return implode(' ', [$this->firstname, $this->lastname]) . " ({$this->email})";
        }
    }
    

    关联的类在序列化过程中仍然通过代理加载。

    最佳答案

    这是迄今为止我想出的最好的解决方案来解决上述问题。它不涉及更改 JMSSerializer 代码。完整代码在此 Gist 中:
    https://gist.github.com/Jaap-van-Hengstum/0d400ea4f986d8f8a044

    诀窍是创建一个空的“假”类:

    namespace MyApp\ApiBundle\Serializer;
    
    class SerializerProxyType
    {
      // this class is supposed to be empty
    }
    

    并在自定义 DoctrineProxySubscriber ,将事件类型设置为该类。这样 JMSSerializer 将使用该类型进行注释处理,因此在遇到类似 @VirtualProperty 的注释时不会触发 Doctrine 代理。 .
    class DoctrineProxySubscriber implements EventSubscriberInterface
    {
        public function onPreSerialize(PreSerializeEvent $event)
        {
            $object = $event->getObject();
            $type = $event->getType();
    
            ...
            // This line is commented, so proxy loading on serializing is disabled
            // $object->__load();
    
            if ( ! $virtualType) {
                // This line is commented because a different type is used
                // $event->setType(get_parent_class($object));
    
                // This assumes that every Doctrine entity has a single 'Id' primary
                // key field.
                $event->setType('MyApp\ApiBundle\Serializer\SerializerProxyType',
                    ["id" => $object->getId()]);
            }
        }
    
        public static function getSubscribedEvents()
        {
            return array(
                array('event' => 'serializer.pre_serialize', 'method' => 'onPreSerialize'),
            );
        }
    }
    

    然后您可以使用 JMSSerializer 处理程序为空类添加自定义处理程序。这个处理程序只会在序列化的 json/xml 中包含实体的 ID:
    class DoctrineProxyHandler implements SubscribingHandlerInterface
    {
        /**
         * {@inheritdoc}
         */
        public static function getSubscribingMethods()
        {
            $methods = [];
    
            foreach (array('json', 'xml') as $format)
            {
                $methods[] = [
                    'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                    'format' => $format,
                    'type' => 'MyApp\\ApiBundle\\Serializer\\SerializerProxyType',
                    'method' => 'serializeTo' . ucfirst($format),
                ];
            }
    
            return $methods;
        }
    
        public function serializeToJson(VisitorInterface $visitor, $entity, array $type, Context $context)
        {
            $object = new \stdClass();
            $object->id = $type['params']['id'];
    
            return $object;
        }
    
        public function serializeToXml(XmlSerializationVisitor $visitor, $entity, array $type, Context $context)
        {
            $visitor->getCurrentNode()->appendChild(
                $node = $visitor->getDocument()->createElement('id', $type['params']['id'])
            );
    
            return $node;
        }
    }
    

    要配置 Symfony 以使用这些类:
    parameters:
        jms_serializer.doctrine_proxy_subscriber.class: MyApp\ApiBundle\Serializer\DoctrineProxySubscriber
    
    services:
      doctrineproxy_handler:
        class: MyApp\ApiBundle\Serializer\DoctrineProxyHandler
        tags:
            - { name: jms_serializer.subscribing_handler }
    

    关于symfony - Doctrine 2 : disable lazy loading/proxy generation.,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27906814/

    相关文章:

    symfony - "the entities are privately owned"是什么意思(如 Doctrine 官方文档中所示)?

    css - 在我自己的包中重新使用 SonataAdminBundle Fontawesome

    php - Doctrine2,setParameter 没有按预期工作

    symfony - VichUploaderBundle:如何获取DirectoryNamer中的相关实体ID?

    doctrine-orm - 不使用指定配置的 Doctrine 迁移

    php - Doctrine Join 表以获得相同的 ID

    php - Doctrine Symfony ORM 不使用 PHP 7.2 生成 MySQL UUID

    mysql - 在 docker-compose build 期间运行数据库迁移失败,但它可以从命令行运行

    php - 如何设置app/cache和app/logs文件夹的权限?

    php - Symfony2 将 4 表内连接查询映射到 Doctrine QueryBuilder