【问题标题】:Repository in PRE_WRITE event returns query data, not saved dataPRE_WRITE 事件中的存储库返回查询数据,而不是保存的数据
【发布时间】:2020-07-28 10:15:38
【问题描述】:

在对项目进行 PUT 调用期间,我需要获取当前保存的值,以便将它们与请求参数进行比较。

假设 PUT 调用包含一个与当前保存的参数不同的name 参数。

我认为使用 $repository->findOneBy 获取实体会返回保存的值,但事实并非如此,我正在获取 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,以便我可以使用getEntityChangeSethasChangedField

【问题讨论】:

    标签: symfony api-platform.com


    【解决方案1】:

    这种行为背后的原因是什么?

    这是教条行为。获取实体后,实例将被存储并始终返回。鉴于此,在请求的生命周期中,您只有一个实体实例。

    $event->getControllerResult() === $repository->findBy($id); //true !
    

    大致来说,Api 平台调用 Doctrine 并在执行 ReadListener 时获取您的实体。因为这是一个对象,所以学说的 find*() 方法总是返回一个指向实体的指针/引用,即使它被更新了。 是的,在 PUT 请求期间,更新的实例是获取的实例,以便在请求结束时触发条令更新操作。

    保留所谓的前一个对象的一个简单方法是在Deserialization event之前clone

    请注意,此策略由 api-platform 与 security_post_denormalizeprevious_object security attributes 一起使用。

    编辑

    在处理类似的用例时,我发现ReadListener 将当前对象存储在“data”键下的Request 中,而前一个对象存储在“previous_data”键中。

    $entity = $request->get('data');
    $previousEntity = $request->get('previous_data'); // This is a clone.
    

    【讨论】:

    • 感谢您的回答,那真的是这样吗?我的目标是设置一个标志,以防某些特定字段被修改。
    • 我从不尝试这样做,但根据this doc,我想可以通过直接使用学说事件订阅者而不是 api 平台订阅者来实现。
    • 好的,谢谢,我希望在 API 平台上下文中这样做,但似乎确实不可能。
    猜你喜欢
    • 1970-01-01
    • 2019-12-05
    • 1970-01-01
    • 2018-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-11
    • 1970-01-01
    相关资源
    最近更新 更多