首页 > 解决方案 > 如何创建可以根据实体当前状态拒绝的自定义更新操作?

问题描述

我正在创建一个自定义PUT操作。

不使用内置操作,因为受影响的属性不包含在该实体的默认规范化中,并且还因为该操作有一些超出该实体/模型的副作用。

此外,只有当数据库上实体的当前状态符合某些预期时,更新操作才会成功。

例如对于实体

class Lead {
    /**
    * @ORM\Column(type="integer", nullable=true)
    * @Groups({"lead", "leadReject" })
    **/
    private $rejectionReason

    public function isRejected() {
       return $this->rejectionReason !== null;

}

我正在创建自定义操作PUT /lead/{id}/reject


class LeadReject {
     public function __invoke( Lead $data ): Lead {

           // if lead is rejected, we need not only to update its status
           // but create an entry in a LeadLog table, and update the state
           // for the Lead owner
     }
}

问题是,当我们到达时__invoke()$data我已经将用户的输入与数据库中的值合并了。因此,任何对的调用$data->isRejected()都会返回 true,即使它仍在null数据库中。

在我持久化对象并执行所有其他操作之前,我需要检查Lead之前没有被拒绝。

我怎样才能做到这一点?可以在操作控制器级别完成吗?我想我可以注入 EntityManager 并再次检索对象,但考虑到此时对象已经被检索到,这似乎很浪费。

标签: symfony4api-platform.com

解决方案


你可以添加一个 Doctrine Listener:

<?php

namespace App\Listener;

use App\Entity\MyEntity;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;

class EntityPreUpdateListener
{
    /**
     * @param MyEntity $entity
     * @param LifecycleEventArgs $args
     */
    public function preUpdate($entity, LifecycleEventArgs $args)
    {
        $entityManager = $args->getObjectManager();
        // do whatever you need

        // you can persist your entity to the database if you need
        $entityManager->flush();

        // detach your entity, so it won't be updated
        $entityManager->detach($entity);
    }
}

只需在您的实体 Doc Block 中添加这一行

@ORM\EntityListeners({"App\Listener\EntityPreUpdateListener"})

您可以在此处查看有关教义事件的更多信息:

https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/events.html


推荐阅读