我正在我的最新项目中使用带有symfony的Doctrine ORM。我需要我的学说默认使用延迟显式跟踪策略 - 我需要控制保存的内容和时间。
我可以在其注释中更改每个实体的学说跟踪策略
/**
* @ORMChangeTrackingPolicy("DEFERRED_EXPLICIT")
*/
但我想将此跟踪策略设为所有实体的默认跟踪策略。我不想仅仅因为这个而创建一个通用的父实体。有没有办法为整个项目设置此跟踪策略默认值?
关于学说跟踪政策。
适合您时间的坦克
DoctrineORMEvents::loadClassMetadata
事件,你可以挂接到并创建一个侦听器,以覆盖实体元数据中的策略。
侦听器是在从注释/yml/xml 加载元数据之后调用的,然后再将它们保存在缓存中,因此它应该非常有效。
- 事件
- :生命周期事件 事件
- :装入类元数据事件
- Symfony:如何注册事件侦听器和订阅者
下面是一些工作代码:
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
:
AppEventSubscriberDoctrineTrackingPolicySubscriber:
tags:
- { name: doctrine.event_subscriber, connection: default }
对于Symfony版本<3.3,指定一个class
是必要的,较新的版本隐式假定服务名称是FQCN。
您可以通过定义自己的工厂来构造DoctrineORMMappingClassMetadata
,将默认更改跟踪策略从延迟隐式更改为延迟显式。
此方法仍允许您的配置指定其中之一,否则仅影响您的配置未另行指定的位置。
<?php
class MyClassMetadataFactory extends DoctrineORMMappingClassMetadataFactory
{
/**
* {@inheritDoc}
*/
protected function newClassMetadataInstance($className)
{
$classMetadata = parent::newClassMetadataInstance($className);
// Change the default Change Tracking Policy to Deferred Explicit.
$classMetadata->setChangeTrackingPolicy(
DoctrineORMMappingClassMetadataInfo::CHANGETRACKING_DEFERRED_EXPLICIT
);
return $classMetadata;
}
}
$xmlMetadataConfig = DoctrineORMToolsSetup::createXMLMetadataConfiguration([__DIR__ . '/config']);
// Set your class to be the factory for ClassMetadata.
$xmlMetadataConfig->setClassMetadataFactoryName(MyClassMetadataFactory::class);
$em = DoctrineORMEntityManager::create(
['pdo' => $pdo],
$xmlMetadataConfig
);
该战略的关键要素如下。
- 重写
DoctrineORMMappingClassMetadataFactory::newClassMetadataInstance()
以更改构造的DoctrineORMMappingClassMetadata
实例的属性。 - 将类设置为要在元数据驱动程序配置中使用的工厂。
我当前的解决方案比在整个项目范围内更改跟踪策略更烦人 - 我必须始终将所有更改的实体传递给 EntityManager->flush($entity=null)。换句话说 - 我必须防止调用没有参数的刷新方法。