Symfony 5:“也许您忘了将其保留在实体管理器中?"->Doctrine折旧的merge()函数的替代方法 [英] Symfony 5: "Maybe you forget to persist it in the entity manager?" --> Alternative for Doctrine's depreciated merge()-function

查看:59
本文介绍了Symfony 5:“也许您忘了将其保留在实体管理器中?"->Doctrine折旧的merge()函数的替代方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我从会话中重新加载对象时,收到错误消息也许您忘记将其保留在实体管理器中了吗?".

When I reload an object from the session, I get an error "Maybe you forget to persist it in the entity manager?".

该怎么办?

推荐答案

在某些情况下,您想在会话中存储数据.总的来说,这在Symfony中可以正常工作.但是,一旦您的数据包含Doctrine实体,您的代码就会早晚爆炸.

There are situations, when you want to store data in sessions. In general this works fine in Symfony. But once your data contains Doctrine-entities, your code will explode sooner or later.

Doctrine正在提出MERGE功能(请参阅: https://www.doctrine-project.org/projects/doctrine-orm/en/2.8/cookbook/entities-in-session.html ),但此功能标记为贬值了.

Doctrine is proposing the MERGE-function (see: https://www.doctrine-project.org/projects/doctrine-orm/en/2.8/cookbook/entities-in-session.html), but this function is marked as depreciated.

在这里,您将找到一个从会话中重新加载后即可恢复教义数据的功能,以使您的代码工作得井井有条.

Here you will find a function to revitalize doctrine-data once loaded back from session to make your code work pretty and nice.

public function anyName() {
  // ...
  $data = $this->session->get('myData', $default_data);
  $data = $this->sessionHelper->revitalizeEntityObjects($data);
  // ...
}

替代MERGE

<?php


namespace App\Service;


use Doctrine\ORM\EntityManagerInterface;
use ReflectionClass;

class SessionHelper
{
    const DB_NAMESPACE_NAME = "App\Entity";

    private $emi;

    public function __construct(EntityManagerInterface $emi) {
        $this->emi = $emi;
    }

    public function revitalizeEntityObjects(object $object)
    {
        $reflect = new ReflectionClass($object);
        $props   = $reflect->getProperties();

        foreach ($props as $prop) {
            $propName = $prop->getName();
            $propName = ucfirst($propName); // capitalize first letter
            $getter   = "get{$propName}";   // name of the getter-function
            $setter   = "set{$propName}";   // name of the setter-function

            // check if the property has a GETTER and SETTER (else go to next property)
            if ( ! $reflect->hasMethod($getter) ) { continue; }
            if ( ! $reflect->hasMethod($setter) ) { continue; }

            // get the value of the property
            $value = $object->$getter();

            // check if the value is an object (else go to next property)
            if ( ! is_object($value)) { continue; }

            // check if the object has the expected namespace-prefix (else go to next property)
            $subReflect = new ReflectionClass($value);
            if ($subReflect->getNamespaceName() !== self::DB_NAMESPACE_NAME) { continue; }

            // check if the ID-Field can be fetched by the standard 'getId'-function
            if ( ! $subReflect->hasMethod('getId') ) { continue; }

            // get the classname of the entity and the repository of that entity
            $classname  = $subReflect->getName();
            $repository = $this->emi->getRepository($classname);

            // re-fetch the object from the database
            $reloadedObject = $repository->find($value->getId());

            // check if something has been fetched (else do nothing and go to next property)
            if ( ! $reloadedObject) { continue; }

            // store the re-fetched object back into the main-object
            $object->$setter($reloadedObject);

        }

        return $object;
    }
}

蒂姆

这篇关于Symfony 5:“也许您忘了将其保留在实体管理器中?"-&gt;Doctrine折旧的merge()函数的替代方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆