我目前正在使用原则合并从会话中检索实体后,通过关系将其“恢复”。
从学说3开始,此功能将被弃用,所以我想知道是否有任何方法可以将实体对象保留在会话中一段时间,然后再将其持久化到数据库中。
我需要一个多步骤表单来填充对象。
目前,我看到的唯一解决方案是将实体存储在临时数据库表中,但是我不太喜欢这个想法,因为我的表将被“垃圾”填充。
谢谢!
我发现了两种方法。
首先是创建自己的实现。我之所以这样,是因为项目中merge
的用法很多。它看起来很黑,但可以运行:
class DoctrineMergeService
{
/**
* @var EntityManager
*/
protected $em;
/**
* @param EntityManager $em
*/
public function __construct(EntityManager $em)
{
$this->em = $em;
}
/**
* @param object $entity
*
* @return object
*
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
* @throws \Doctrine\ORM\TransactionRequiredException
*/
public function mergeEntityToDoctrine(object $entity): object
{
$mergedEntity = null;
$className = get_class($entity);
$identifiers = $this->getIdentifiersFromEntity($entity);
$entityFromDoctrine = $this->em->find($className, $identifiers);
if ($entityFromDoctrine) {
$mergedEntity = $this->mergeEntities($entityFromDoctrine, $entity);
} else {
$this->em->persist($entity);
$mergedEntity = $entity;
}
return $mergedEntity;
}
/**
* @param object $entity
*
* @return array
*/
private function getIdentifiersFromEntity(object $entity): array
{
$className = get_class($entity);
$meta = $this->em->getClassMetadata($className);
$identifiers = $meta->getIdentifierValues($entity);
return $identifiers;
}
/**
* @param object $first
* @param object $second
*
* @return object
*/
private function mergeEntities(object $first, object $second): object
{
$classNameFirst = get_class($first);
$metaFirst = $this->em->getClassMetadata($classNameFirst);
$classNameSecond = get_class($second);
$metaSecond = $this->em->getClassMetadata($classNameSecond);
$fieldNames = $metaFirst->getFieldNames();
foreach ($fieldNames as $fieldName) {
$secondValue = $metaSecond->getFieldValue($second, $fieldName);
$metaFirst->setFieldValue($first, $fieldName, $secondValue);
}
return $first;
}
}
第二个是使用serializer,未经测试:
// this is controller or analogue
public function save($id)
{
$serializedJsonFromSession = $this->session->get('serialized_json');
$doctrine = $this->getDoctrine();
$entity = $doctrine->getRepository(Entity::class)->find($id);
if (!$entity) {
$entity = new Entity();
$doctrine->persist($entity);
}
$serializer->deserialize(
$serializedJsonFromSession,
Entity::class,
'json',
[AbstractNormalizer::OBJECT_TO_POPULATE => $entity]
);
$doctrine->flush();
}