Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/247.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何将默认跟踪策略更改为延迟显式_Php_Orm_Doctrine Orm_Doctrine - Fatal编程技术网

Php 如何将默认跟踪策略更改为延迟显式

Php 如何将默认跟踪策略更改为延迟显式,php,orm,doctrine-orm,doctrine,Php,Orm,Doctrine Orm,Doctrine,我正在将ORM与symfony一起用于我的最新项目。我需要我的原则在默认情况下使用延迟显式跟踪策略-我需要控制保存内容和时间 我可以在注释中更改每个实体的条令跟踪策略 /** * @ORM\ChangeTrackingPolicy("DEFERRED_EXPLICIT") */ 但我想让所有实体都默认使用此跟踪策略。我不想仅仅因为这个就创建一个公共的父实体。有没有办法为整个项目设置此跟踪策略默认值 关于学说 我当前的解决方案比在整个项目范围内更改跟踪策略要烦人一点-我必须始终将所有更改的实体传

我正在将ORM与symfony一起用于我的最新项目。我需要我的原则在默认情况下使用延迟显式跟踪策略-我需要控制保存内容和时间

我可以在注释中更改每个实体的条令跟踪策略

/**
* @ORM\ChangeTrackingPolicy("DEFERRED_EXPLICIT")
*/
但我想让所有实体都默认使用此跟踪策略。我不想仅仅因为这个就创建一个公共的父实体。有没有办法为整个项目设置此跟踪策略默认值

关于学说


我当前的解决方案比在整个项目范围内更改跟踪策略要烦人一点-我必须始终将所有更改的实体传递给。换句话说,我必须防止在没有参数的情况下调用flush方法。

有一个
原则\ORM\Events::loadClassMetadata
事件,您可以连接到该事件中并创建一个侦听器来覆盖实体元数据中的策略

从annotations/yml/xml加载元数据之后,在将元数据保存到缓存中之前,会调用侦听器,因此它应该非常有效

下面是一些工作代码:

class DoctrineTrackingPolicySubscriber implements EventSubscriber
{
    public function getSubscribedEvents()
    {
        return [
            Events::loadClassMetadata
        ];
    }

    public function loadClassMetadata(LoadClassMetadataEventArgs $args)
    {
        $classMetadata = $args->getClassMetadata();
        $classMetadata->setChangeTrackingPolicy(
            ClassMetadataInfo::CHANGETRACKING_DEFERRED_EXPLICIT
        );
    }
}
然后在
services.yaml
services.yml
中:

App\EventSubscriber\DoctrineTrackingPolicySubscriber:
    tags:
        - { name: doctrine.event_subscriber, connection: default }

对于Symfony版本<3.3,需要指定
类别
,较新版本隐式假定服务名称为FQCN。

通过定义自己的工厂来构造
\doctor\ORM\Mapping\ClassMetadata
,可以将默认更改跟踪策略从延迟隐式更改为延迟显式

此方法仍然允许您的配置指定其中之一,并且仅影响您的配置未指定其他方法的情况

<?php

class MyClassMetadataFactory extends Doctrine\ORM\Mapping\ClassMetadataFactory
{
    /**
     * {@inheritDoc}
     */
    protected function newClassMetadataInstance($className)
    {
        $classMetadata = parent::newClassMetadataInstance($className);

        // Change the default Change Tracking Policy to Deferred Explicit.
        $classMetadata->setChangeTrackingPolicy(
            Doctrine\ORM\Mapping\ClassMetadataInfo::CHANGETRACKING_DEFERRED_EXPLICIT
        );

        return $classMetadata;
    }
}

$xmlMetadataConfig = \Doctrine\ORM\Tools\Setup::createXMLMetadataConfiguration([__DIR__ . '/config']);

// Set your class to be the factory for ClassMetadata.
$xmlMetadataConfig->setClassMetadataFactoryName(MyClassMetadataFactory::class);

$em = Doctrine\ORM\EntityManager::create(
    ['pdo' => $pdo],
    $xmlMetadataConfig
);

这意味着您将动态更改每个类(但不是每个实例)的实体跟踪策略。这是一个可以接受的解决方案,如果有人发现一些更明显的问题(比如一个教义设置),我会给他几天时间。无论如何,谢谢-Díky Filipe:)注意,使用Load ClassMetadata事件将允许您覆盖任何实体的指定更改跟踪策略,但是当实体没有另外指定时,更改默认策略是不起作用的。最好使用listener而不是subscriber,因为订阅者必须始终被实例化,即使没有使用,而listener仅在实际需要时才被实例化(谈到条令订阅者,symfony订阅者的行为不同)@Rikudou_Sennin Symfony最近引入了对懒惰主义的支持subscribers@FilipProcházka在任何地方都找不到它,是否要共享一个链接?这需要重写不打算被重写且对性能非常敏感的类。使用监听器可以实现同样的、更干净的效果,因为监听器是一个扩展点。@Filiprocházka-挂接到事件监听器并不能提供更改实体默认策略的方法(如果我错了,请演示)我也有点怀疑这样一个论点,即在构造实体管理器时,当条令将类作为配置选项提供时,该类不应被重写。您在技术上是正确的(在此处插入技术上正确的模因),但侦听器实现了相同的结果,我的主要论点——更清楚地说,因为它是专用的扩展点。可以重写该类,但应尽可能避免使用它。