PRE_WRITE事件中的存储库返回查询数据,而不是已保存的数据 [英] Repository in PRE_WRITE event returns query data, not saved data

查看:94
本文介绍了PRE_WRITE事件中的存储库返回查询数据,而不是已保存的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在对项目进行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屋!

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