PRE_WRITE事件中的存储库返回查询数据,而不是已保存的数据 [英] Repository in PRE_WRITE event returns query data, not saved data
问题描述
在对项目进行PUT调用期间,我需要获取当前保存的值,以便将它们进行比较以请求参数.
During a PUT call to an item I need to get the current saved values in order to compare them to request params.
说PUT调用包含一个 name
参数,该参数与当前保存的参数不同.
Say the PUT call contains a name
parameter that is different from the currently saved one.
我认为使用 $ repository-> findOneBy
获取实体会返回保存的值,但事实并非如此,而是获取PUT参数值.
I thought getting the entity with $repository->findOneBy
would return the saved value but it's not, I'm getting the PUT param value instead.
此设置来自 https://api-platform.com/docs/core/事件:
const ALLOWED_METHOD = Request::METHOD_PUT;
public static function getSubscribedEvents()
{
return [
KernelEvents::VIEW => [
['preWriteWorkflow', EventPriorities::PRE_WRITE],
],
];
}
public function preWriteWorkflow(GetResponseForControllerResultEvent $event)
{
$entity = $event->getControllerResult();
if (!($entity instanceof MyEntity)) {
return;
}
$route = "/{$entity->getId()}";
$result = $this->checkRequestFromControllerResult($event, $route);
if (!$result) {
return;
}
// Getting entity from repository in order to get the currently saved value
$savedEntity = $this->MyEntityRepository->findOneBy(['id' => $entity->getId()]);
// Both will return the Name value of the PUT call
// Shouldn't $savedEntity return the currently saved name ?
$entity->getName();
$savedEntity->getName();
}
此行为背后的原因是什么?有没有办法以这种方法注入 eventArgs
,以便我可以使用 getEntityChangeSet
或 hasChangedField
?
What is the reason behind this behavior? Is there a way to get eventArgs
injected in this method so that I can use getEntityChangeSet
or hasChangedField
?
推荐答案
此行为背后的原因是什么?
What is the reason behind this behavior?
这是教义上的行为.获取实体后,实例将被存储并始终返回.鉴于此,在请求的生命周期中,您只有一个实体实例.
This is doctrine behaviour. Once you've fetched an entity, the instance is stored and always returned. Given that, you have one and only one instance of your entity during request's lifecycle.
$event->getControllerResult() === $repository->findBy($id); //true !
大致上,Api平台在执行ReadListener时会调用Doctrine并获取您的实体.因为这是一个对象,所以学说的 find *()方法始终返回指向实体的指针/引用,即使该实体已更新也是如此.是的,在PUT请求期间,已更新的实例是已获取的实例,以便在请求结束时触发教义更新操作.
Roughly, Api-platform calls Doctrine and fetch your entity while executing the ReadListener. Because this is an object, doctrine's find*() methods always returns a pointer/reference to the entity, even if it is updated. Yes, during a PUT request, the updated instance is the fetched one, in order to trigger doctrine update actions at the end of the request.
保留所谓的先前对象实例的一种简单方法是 反序列化事件.
An easy way to keep an instance of the so called previous object is to clone it before the Deserialization event.
请注意,api-platform和 security_post_denormalize
和 previous_object
Note that this strategy is used by api-platform with the security_post_denormalize
and previous_object
security attributes.
编辑
在类似的用例上,我发现 ReadListener
将当前对象存储在 Request
中的数据"下方.键,而先前的对象则存储在"previous_data"字段中.键.
Working on a similar use case, i've found that the ReadListener
stores the current object within the Request
under the "data" key, whereas the previous object is stored within the "previous_data" key.
$entity = $request->get('data');
$previousEntity = $request->get('previous_data'); // This is a clone.
这篇关于PRE_WRITE事件中的存储库返回查询数据,而不是已保存的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!