Symfony 5: "Maybe you forget to persist it in the entity manager?" --> Doctrine 贬值的 merge() 函数的替代方案
Symfony 5: "Maybe you forget to persist it in the entity manager?" --> Alternative for Doctrine's depreciated merge()-function
当我从会话中重新加载对象时,出现错误“您可能忘记将它保存在实体管理器中?”。
可以做什么?
有些情况下,您希望在会话中存储数据。一般来说,这在 Symfony 中运行良好。但是一旦你的数据包含 Doctrine-entities,你的代码迟早会爆炸。
Doctrine 正在提议 MERGE 函数(参见:https://www.doctrine-project.org/projects/doctrine-orm/en/2.8/cookbook/entities-in-session.html),但此函数已标记为已弃用。
在这里,您会发现一个函数,一旦从会话中加载回来,就可以使 doctrine-data 恢复活力,从而使您的代码工作得非常好。
用法
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 中运行良好。但是一旦你的数据包含 Doctrine-entities,你的代码迟早会爆炸。
Doctrine 正在提议 MERGE 函数(参见:https://www.doctrine-project.org/projects/doctrine-orm/en/2.8/cookbook/entities-in-session.html),但此函数已标记为已弃用。
在这里,您会发现一个函数,一旦从会话中加载回来,就可以使 doctrine-data 恢复活力,从而使您的代码工作得非常好。
用法
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;
}
}
蒂姆