Symfony 5:“也许您忘了将其保留在实体管理器中?"->Doctrine折旧的merge()函数的替代方法 [英] Symfony 5: "Maybe you forget to persist it in the entity manager?" --> Alternative for Doctrine's depreciated merge()-function
问题描述
当我从会话中重新加载对象时,收到错误消息也许您忘记将其保留在实体管理器中了吗?".
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:“也许您忘了将其保留在实体管理器中?"->Doctrine折旧的merge()函数的替代方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!