使用Doctrine,我想分离()一个实体。
在flush()之前,我使用:
$entityManager->detach($entity);
但是我的实体更新了 PersistentCollection 。此Collection位于UnitOfWork的getScheduledCollectionUpdates()中:
foreach ($uow->getScheduledCollectionUpdates() as $col) {
dump($col); // entity was here
}
我想使用Collection(=删除所有更改)来分离所有实体。
修改:
这是我在 computeChangeSets() 之前的UnifOfWOrk:
我想分离PersistentCollection#1562。 Media#750 id已分离(Proxies__CG __ \ AppBundle \ Entity \ Media),但她的收藏品尚未分离。
这是Subscriber(用于保留所有版本的实体)。分离已在 copyEntity()中执行:
namespace AppBundle\EventListener;
use AppBundle\Annotation\Versionable;
use AppBundle\Annotation\VersionableField;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\PersistentCollection;
use Symfony\Component\PropertyAccess\PropertyAccess;
class DoctrineSubscriber implements EventSubscriber
{
private $accessor;
private $annotationReader;
private $entitiesUpdated = [];
public function __construct() {
$this->accessor = PropertyAccess::createPropertyAccessor();
$this->annotationReader = new AnnotationReader();
}
public function getSubscribedEvents()
{
return [
'onFlush',
];
}
public function onFlush(OnFlushEventArgs $args)
{
$entityManager = $args->getEntityManager();
$uow = $entityManager->getUnitOfWork();
if (!empty($uow->getScheduledEntityUpdates()) || !empty($uow->getScheduledCollectionUpdates())) {
foreach ($uow->getIdentityMap() as $entities) {
foreach ($entities as $entity) {
$class = get_class($entity);
$metaData = $entityManager->getClassMetadata($class);
if (array_key_exists('versions', $metaData->associationMappings) && null !== $entity->getVersions()) {
$property = new \ReflectionProperty($metaData->getName(), 'versions');
$annotation = $this->annotationReader->getPropertyAnnotation($property, Versionable::class);
if ($annotation !== null) {
if (true === in_array($entity->getVersions()->last(), $uow->getScheduledEntityUpdates()) || true === $this->checkIfEntityIsUpdated($entityManager, $entity->getVersions()->last())) {
$entity->addVersion($this->copyEntity($entityManager, $entity->getVersions()->last()));
foreach ($entity->getVersions() as $version) {
if ($version !== $entity->getVersions()->last()) {
$entity->getVersions()->removeElement($version);
$entityManager->detach($version);
}
}
}
}
}
}
}
}
$uow->computeChangeSets();
}
public function checkIfEntityIsUpdated(EntityManager $entityManager, $entity)
{
if (in_array($entity, $this->entitiesUpdated)) {
return true;
}
$uow = $entityManager->getUnitOfWork();
if (in_array($entity, $uow->getScheduledEntityUpdates())) {
$this->entitiesUpdated[] = $entity;
return true;
} else {
$class = get_class($entity);
$metaData = $entityManager->getClassMetadata($class);
$reflection = new \ReflectionClass($metaData->getName());
foreach($reflection->getProperties() as $property) {
$annotation = $this->annotationReader->getPropertyAnnotation($property, VersionableField::class);
if ($annotation !== null) {
if (array_key_exists($property->getName(), $metaData->associationMappings)) {
$value = $this->accessor->getValue($entity, $property->getName());
if ($value !== null) {
if($value instanceof PersistentCollection) {
if (in_array($value, $uow->getScheduledCollectionUpdates())) {
$this->entitiesUpdated[] = $value;
return true;
}
} else {
if (in_array($value, $uow->getScheduledEntityUpdates())) {
$this->entitiesUpdated[] = $value;
return true;
}
if (true === $this->checkIfEntityIsUpdated($entityManager, $value)) {
return true;
}
}
}
}
}
}
}
return false;
}
private function copyEntity(EntityManager $entityManager, $from)
{
$metaData = $entityManager->getClassMetadata(get_class($from));
$toName = $metaData->getName();
$to = new $toName;
$reflection = new \ReflectionClass($metaData->getName());
foreach($reflection->getProperties() as $property) {
$annotation = $this->annotationReader->getPropertyAnnotation($property, VersionableField::class);
if ($annotation !== null) {
$value = $this->accessor->getValue($from, $property->getName());
if (array_key_exists($property->getName(), $metaData->associationMappings)) {
if($value instanceof PersistentCollection) {
if (in_array($value, $entityManager->getUnitOfWork()->getScheduledCollectionUpdates())) {
foreach ($value as $element) {
if (true === $this->checkIfEntityIsUpdated($entityManager, $element)) {
dump('CAS A PREVOIR mais pas sur quil soit différent du cas en dessous');
exit;
} else {
$newElement = $this->copyEntity($entityManager, $element);
if (isset($metaData->associationMappings[$property->getName()]['mappedBy'])) {
$this->accessor->setValue($newElement, $metaData->associationMappings[$property->getName()]['mappedBy'], $to);
}
$this->accessor->getValue($to, $property->getName())->add($newElement);
$this->accessor->getValue($from, $property->getName())->removeElement($element);
}
}
}
} elseif (null === $value) {
$this->accessor->setValue($to, $property->getName(), null);
} else {
if (true === $this->checkIfEntityIsUpdated($entityManager, $value)) {
$this->accessor->setValue($to, $property->getName(), $this->copyEntity($entityManager, $value));
} else {
$this->accessor->setValue($to, $property->getName(), $value);
}
}
} else {
$this->accessor->setValue($to, $property->getName(), $value);
}
}
}
$entityManager->detach($from);
$entityManager->persist($to);
return $to;
}
}
答案 0 :(得分:0)
你在什么时候分开?如果您在doctrine onFlush listener或更高版本(preUpdate)中执行此操作,则已经计算了更改集。尝试在preFLush中执行此操作。或者,您可以通过调用
手动触发更改集的计算 $unitOfWork->computeChangeSets()
;
查看学说事件的更多详情here