我正在尝试记录给定项目的数量变化。为此,我听了 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;
}
}
答案 0 :(得分:0)
我发现问题出在getUserByRequest()
函数中实例化了实体管理器的另一个实例,在该函数中,我记录了使用用户令牌的情况。除其他外,我在其中创建了一个新管理器,将条目保留下来并刷新结果。但是,新的实体管理器不知道侦听器内另一个实体管理器内部的工作单元。因此,出现未定义的索引错误。
我试图省略用户getter函数中的persist和flush部分,但这还不够。最后,我通过将给定的实例实体管理器从侦听器内部传递到getter函数来解决了这个问题。因此,基本上,我最终从侦听器中的preUpdateHandler
函数调用了此代码。
$em = $args->getEntityManager();
$company = $this->userProvider->getUserByRequest($request, $em);
希望这对您在类似的泡菜中很有帮助。