原则 3 合并替代方案

gea*_*lex 3 php doctrine

我目前正在使用学说合并来“恢复”从会话中检索实体后的关系。

从原则 3 开始,这个函数将被弃用,所以我想知道是否有任何方法可以在将实体对象保存到数据库之前将其保留在会话中一段时间​​。

我需要这个多步骤表单来填充我的对象。

目前,我看到的唯一解决方案是将实体存储在临时数据库表中,但我不太喜欢这个想法,因为我的表将充满“垃圾”。

谢谢 !

小智 5

我发现有两种方法。

第一个是创建您自己的实现。我之所以走这条路是因为项目中有很多用法merge。它看起来很老套,但很有效:

class DoctrineMergeService
{
    /**
     * @var EntityManager
     */
    private $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 merge(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;
    }
}
Run Code Online (Sandbox Code Playgroud)

第二种是使用序列化器,未测试:

// this is controller or something like controller
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();
}
Run Code Online (Sandbox Code Playgroud)