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

查看:19
本文介绍了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 以便我可以使用 getEntityChangeSethasChangedField?

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.

保留所谓的前一个对象实例的一种简单方法是clone反序列化事件.

An easy way to keep an instance of the so called previous object is to clone it before the Deserialization event.

请注意,此策略由带有 security_post_denormalizeprevious_object 的 api-platform 使用 安全属性.

Note that this strategy is used by api-platform with the security_post_denormalize and previous_object security attributes.

编辑

在处理一个类似的用例时,我发现 ReadListener 将当前对象存储在 Request 中的data"下.键,而前一个对象存储在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天全站免登陆