Symfony: создайте новую сущность внутри доктрины EntityListener с ассоциацией ManyToOne - PullRequest
0 голосов
/ 30 декабря 2018

Я пытаюсь записать каждое изменение количества данного товара.Для этого я ожидаю изменения сущности Item и хочу создать новый экземпляр Transaction с подробными сведениями о действии.Итак, я создаю сущность внутри слушателя.

Я настроил все в соответствии с документацией и создал слушателя на основе этого примера.

Код (я считаю) имеет отношение к моей проблеме следующим образом.

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

Это работает отлично.Однако проблема заключается в том, что я добавляю еще одно поле в объект транзакции.Поле user внутри Transaction имеет отношение ManyToOne.Теперь, когда я пытаюсь установить пользователя внутри preUpdateHandler, это приводит к неопределенной ошибке индекса внутри функции UnitOfWork в Entity Manager.

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.Однако этот метод не определен для прослушивателей Entity в соответствии с документацией, и, если возможно, я бы хотел придерживаться такого прослушивателя, а не прослушивателя событий.

Спасибо за любую помощь.Я также включаю код объекта транзакции на всякий случай.

Объект транзакции

  <?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 голосов
/ 03 января 2019

Я обнаружил, что проблема была в том, что другой экземпляр менеджера сущностей был создан в функции getUserByRequest(), где я регистрирую, что использовался токен пользователя.Помимо других, я создал внутри него нового менеджера, сохранил запись и очистил результат.Однако новый менеджер сущностей не знает о единице работы внутри другого менеджера сущностей внутри слушателя.Отсюда и неопределенная ошибка индекса.

Я попытался пропустить часть persist и flush в пользовательской функции получения, но этого было недостаточно.В конце концов, я решил проблему, передав данный менеджер экземпляра сущности из слушателя в функцию получения.В общем, в итоге я вызвал это из функции preUpdateHandler внутри слушателя.

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

Надеюсь, это поможет, если вы окажетесь в подобном рассоле.

...