如何创建可根据实体当前状态拒绝的自定义更新操作?

时间:2019-06-24 09:47:47

标签: symfony4 api-platform.com

我正在创建自定义package anubhav.calculatorapp; import android.util.Log; import java.lang.reflect.Method; public class jacoco { static void generateCoverageReport() { String TAG = "jacoco"; // use reflection to call emma dump coverage method, to avoid // always statically compiling against emma jar String coverageFilePath = "/sdcard/coverage.exec"; java.io.File coverageFile = new java.io.File(coverageFilePath); try { Class<?> emmaRTClass = Class.forName("com.vladium.emma.rt.RT"); Method dumpCoverageMethod = emmaRTClass.getMethod("dumpCoverageData", coverageFile.getClass(), boolean.class, boolean.class); dumpCoverageMethod.invoke(null, coverageFile, false, false); Log.e(TAG, "generateCoverageReport: ok"); } catch (Exception e) { Log.e("jacoco", "inside catch. no emma jar found"); new Throwable("Is emma jar on classpath?", e); } } } 操作。

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

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

例如对于实体

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的任何调用都将返回true,即使它仍在数据库中$data->isRejected()上也是如此。

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

我该怎么做?可以在操作控制器级别完成吗?我想我可以注入EntityManager并再次检索该对象,但是考虑到此刻该对象已经被检索,这似乎是浪费的。

3 个答案:

答案 0 :(得分:0)

您可以添加一个教义监听器:

<?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);
    }
}

然后将这一行添加到您的实体文档块中

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

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

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

答案 1 :(得分:0)

关闭对象的自动加载,以便从Controller检索对象不会使用任何额外资源:

/*
 * @ApiResource(
 *     itemOperations={
 *         "put"={
 *             "read"=false
 *         }
 * )
 */
class Lead {

答案 2 :(得分:0)

让实体暂时记住更改:

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

    /** @var int|null Not mapped to the db */
    private $previousRejectionReason; 

    public function setRejectionReason($value)
    {
         $this->previousRejectionReason = $this->rejectionReason;
         $this->rejectionReason = $value;
    }

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

    public function wasAlreadyRejected() {
        return $this->previousRejectionReason !== null;
    }
}

(通过检查Doctrines $ entityManager :: getUnitOfWork-> getEntityChangeSet($ lead)中的属性是否已更改,可以获得类似的结果,但是我想这不是您要查找的内容...)

相关问题