[英]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.yaml
或services.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. 该策略的关键要素如下。
\\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
的构造实例的属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.