Symfony:在具有ManyToOne关联的学说EntityListener内部创建新实体

时间:2018-12-30 19:27:09

标签: symfony doctrine

我正在尝试记录给定项目的数量变化。为此,我听了 Item 实体的更改,并希望创建一个新的 Transaction 实例,其中包含有关操作的详细信息。因此,我正在侦听器内部创建一个实体。

我已经根据documentation设置了所有内容,并根据this示例创建了侦听器。

以下是与我的问题相关的代码。

ItemListener

// ...
private $log;
/** @ORM\PreUpdate */
public function preUpdateHandler (Item $item, PreUpdateEventArgs $args)
{
    $changeSet = $args->getEntityManager()->getUnitOfWork()->getEntityChangeSet($item)['quantity'];
    $quantityChange = $changeSet[1] - $changeSet[0];

    $transaction = new Transaction();
    $transaction->setItem($item);
    $transaction->setQuantityChange($quantityChange);

    $this->log = $transaction;
}

/** @ORM\PostUpdate */
public function postUpdateHandler(Item $item, LifecycleEventArgs $args)
{
    $em = $args->getEntityManager();
    $em->persist($this->log);
    $em->flush();
}

这很好用。但是,问题是当我向交易实体添加另一个字段时。 Transaction 实体内的 user 字段具有ManyToOne关系。现在,当我尝试在preUpdateHandler内设置用户时,会导致在实体管理器的UnitOfWork函数内出现未定义的索引错误。

Notice: Undefined index: 000000003495bf92000000001108e474 

监听器现在是这样的。我根据与请求一起发送的令牌检索用户。因此,我将请求堆栈和自定义用户提供程序注入侦听器的构造函数中。我认为这不是问题的根源。但是,如有必要,我将编辑该帖子并添加所有剩余的代码(侦听器的其余部分,services.yaml和用户提供程序)。

ItemListener

// ...
private $log;
/** @ORM\PreUpdate */
public function preUpdateHandler (Item $item, PreUpdateEventArgs $args)
{
    $changeSet = $args->getEntityManager()->getUnitOfWork()->getEntityChangeSet($item)['quantity'];
    $quantityChange = $changeSet[1] - $changeSet[0];

    $transaction = new Transaction();
    $transaction->setItem($item);
    $transaction->setQuantityChange($quantityChange);

    $request = $this->requestStack->getCurrentRequest();
    $company = $this->userProvider->getUserByRequest($request);

    $this->log = $transaction;
}

/** @ORM\PostUpdate */
public function postUpdateHandler(Item $item, LifecycleEventArgs $args)
{
    $em = $args->getEntityManager();
    $em->persist($this->log);
    $em->flush();
}

我不明白为什么通过检索另一个实体来取回同花顺会导致该错误。在寻找答案时,我发现很多人建议不要在flush()周期内使用postUpdate,而应该在postFlush中使用。但是,根据文档未为实体侦听器定义此方法,如果可能,我想坚持使用此类侦听器,而不是事件侦听器。

感谢您的帮助。我还包括了交易实体代码,以防万一。

交易实体

  <?php

  namespace App\Entity;

  use Doctrine\ORM\Mapping as ORM;
  use App\DoctrineUtils\MagicAccessors;
  use App\Entity\T\TIdentifier;

/**
 * @ORM\Entity
 * @ORM\Table(name="transaction")
 */
 class Transaction
 {
  use TIdentifier;
  use MagicAccessors;

  /**
  * @ORM\ManyToOne(targetEntity="Item")
  * @ORM\JoinColumn(name="item_id", referencedColumnName="id", nullable=false)
  */
  public $item;

  /**
  * @ORM\Column(type="decimal", length=14, precision=4, nullable=false)
  */
  public $quantityChange;


  /**
  * @ORM\Column(type="datetime", nullable=true)
  */
  private $createdTime;

  /**
  * @ORM\ManyToOne(targetEntity="App\Entity\User")
  * @ORM\JoinColumn(nullable=false)
  */
  private $user;


  public function __construct()
  {
     $this->createdTime = new \DateTime();
  }

  /**
  * @param mixed $quantityChange
  */
  public function setQuantityChange(int $quantityChange): void
  {
    $this->quantityChange = $quantityChange;
  }

  /**
  * @param mixed $createdTime
  */
  public function setCreatedTime($createdTime): void
  {
    $this->createdTime = $createdTime;
  }

  /** @ORM\PrePersist **/
  public function onCreate() : void
  {
    $this->setCreatedTime(new \DateTime('now'));
  }

  public function setUser(?User $user): self
  {
    $this->user= $user;

    return $this;
  }
}

1 个答案:

答案 0 :(得分:0)

我发现问题出在getUserByRequest()函数中实例化了实体管理器的另一个实例,在该函数中,我记录了使用用户令牌的情况。除其他外,我在其中创建了一个新管理器,将条目保留下来并刷新结果。但是,新的实体管理器不知道侦听器内另一个实体管理器内部的工作单元。因此,出现未定义的索引错误。

我试图省略用户getter函数中的persist和flush部分,但这还不够。最后,我通过将给定的实例实体管理器从侦听器内部传递到getter函数来解决了这个问题。因此,基本上,我最终从侦听器中的preUpdateHandler函数调用了此代码。

$em = $args->getEntityManager();
$company = $this->userProvider->getUserByRequest($request, $em);

希望这对您在类似的泡菜中很有帮助。