PRE_WRITE 事件中的存储库 returns 查询数据,未保存数据
Repository in PRE_WRITE event returns query data, not saved data
在对项目进行 PUT 调用期间,我需要获取当前保存的值以便将它们与请求参数进行比较。
假设 PUT 调用包含一个 name
与当前保存的参数不同的参数。
我认为使用 $repository->findOneBy
获取实体会 return 保存的值,但事实并非如此,我正在获取 PUT 参数值。
设置取自https://api-platform.com/docs/core/events :
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?
这是主义行为。获取实体后,实例将被存储并始终返回。鉴于此,在请求的生命周期中,您只有一个实体实例。
$event->getControllerResult() === $repository->findBy($id); //true !
粗略地说,Api-platform 在执行 ReadListener 时调用 Doctrine 并获取您的实体。因为这是一个对象,所以 doctrine 的 find*() 方法总是 returns a pointer/reference 到实体,即使它被更新了。
是的,在 PUT 请求期间,更新的实例是获取的实例,以便在请求结束时触发准则更新操作。
保留所谓的 previous object 实例的一种简单方法是 clone it before the Deserialization event.
请注意,此策略由 api-平台使用 security_post_denormalize
和 previous_object
security attributes。
编辑
处理类似的用例,我发现 ReadListener
将当前对象存储在 Request
中的“数据”键下,而前一个对象存储在“ previous_data" 键。
$entity = $request->get('data');
$previousEntity = $request->get('previous_data'); // This is a clone.
在对项目进行 PUT 调用期间,我需要获取当前保存的值以便将它们与请求参数进行比较。
假设 PUT 调用包含一个 name
与当前保存的参数不同的参数。
我认为使用 $repository->findOneBy
获取实体会 return 保存的值,但事实并非如此,我正在获取 PUT 参数值。
设置取自https://api-platform.com/docs/core/events :
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?
这是主义行为。获取实体后,实例将被存储并始终返回。鉴于此,在请求的生命周期中,您只有一个实体实例。
$event->getControllerResult() === $repository->findBy($id); //true !
粗略地说,Api-platform 在执行 ReadListener 时调用 Doctrine 并获取您的实体。因为这是一个对象,所以 doctrine 的 find*() 方法总是 returns a pointer/reference 到实体,即使它被更新了。 是的,在 PUT 请求期间,更新的实例是获取的实例,以便在请求结束时触发准则更新操作。
保留所谓的 previous object 实例的一种简单方法是 clone it before the Deserialization event.
请注意,此策略由 api-平台使用 security_post_denormalize
和 previous_object
security attributes。
编辑
处理类似的用例,我发现 ReadListener
将当前对象存储在 Request
中的“数据”键下,而前一个对象存储在“ previous_data" 键。
$entity = $request->get('data');
$previousEntity = $request->get('previous_data'); // This is a clone.