简体   繁体   English

如何将Doctrine ORM默认跟踪策略更改为Deferred Explicit

[英]How to change Doctrine ORM default tracking policy to Deferred Explicit

I am using Doctrine ORM with symfony for my latest project. 我将带有symfony的Doctrine ORM用于我的最新项目。 I need my doctrine to use Deferred Explicit tracking policy by default - I need to control what and when to save. 我需要我的学说默认情况下使用Deferred Explicit跟踪策略-我需要控制保存时间和内容。

I can change doctrine tracking policy for each entity in its annotations 我可以在其注释中更改每个实体的学说跟踪政策

/**
* @ORM\ChangeTrackingPolicy("DEFERRED_EXPLICIT")
*/

but I would like to make this tracking policy default for all entities. 但我想将此跟踪策略默认为所有实体。 I don't want to create a common parent entity just because of this. 正因为如此,我不想创建一个公共的父实体。 Is there any way to set this tracking policy default for a whole project? 有什么方法可以将整个项目的跟踪策略设置为默认值?

About doctrine tracking policies . 关于学说追踪政策

Tanks for your time 你的时间的坦克

There is a Doctrine\\ORM\\Events::loadClassMetadata event, that you can hook into and create a listener that overwrites the policy in entity metadata. 有一个Doctrine\\ORM\\Events::loadClassMetadata事件,您可以挂钩并创建一个侦听器来覆盖实体元数据中的策略。

The listener is called after metadata are loaded from annotations/yml/xml, before they're saved in cache, so it should be very effective. 在从注解/ yml / xml加载元数据之后,在将它们保存到缓存之前,将调用侦听器,因此它应该非常有效。

Here's some working code: 这是一些工作代码:

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

    public function loadClassMetadata(LoadClassMetadataEventArgs $args)
    {
        $classMetadata = $args->getClassMetadata();
        $classMetadata->setChangeTrackingPolicy(
            ClassMetadataInfo::CHANGETRACKING_DEFERRED_EXPLICIT
        );
    }
}

Then in services.yaml or services.yml : 然后在services.yamlservices.yml

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

For Symfony versions < 3.3 specifying a class will be necessary, newer versions implicitly assume service name is FQCN. 对于<3.3的Symfony版本,必须指定一个class ,较新的版本隐式假定服务名称为FQCN。

My current solution is just a little more annoying than changing tracking policy project-wide - I have to always pass all my changed entities to EntityManager->flush($entity=null) . 我当前的解决方案仅比在整个项目范围内更改跟踪策略更令人讨厌-我必须始终将所有更改后的实体传递给EntityManager-> flush($ entity = null) In other words - I have to prevent calling flush method without parameters. 换句话说-我必须防止没有参数的情况下调用flush方法。

You can change the default change tracking policy from Deferred Implicit to Deferred Explicit by defining your own factory for constructing \\Doctrine\\ORM\\Mapping\\ClassMetadata . 您可以通过定义自己的工厂来构造\\Doctrine\\ORM\\Mapping\\ClassMetadata从而将默认更改跟踪策略从Deferred Implicit更改为Deferred Explicit

This method still allows your for your configuration to specify either, and otherwise only impacts where you configuration does not specify otherwise. 此方法仍然允许您为配置指定任何一个,否则仅影响配置中未指定的地方。

<?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
);

The key elements of this strategy are the following. 该策略的关键要素如下。

  • Override \\Doctrine\\ORM\\Mapping\\ClassMetadataFactory::newClassMetadataInstance() to change the properties of the constructed instance of \\Doctrine\\ORM\\Mapping\\ClassMetadata . 重写\\Doctrine\\ORM\\Mapping\\ClassMetadataFactory::newClassMetadataInstance()以更改\\Doctrine\\ORM\\Mapping\\ClassMetadata的构造实例的属性。
  • Set your class as the factory to be used in the configuration of the Metadata Driver. 将您的类设置为在元数据驱动程序的配置中使用的工厂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM