Doctrine - обновите множество ассоциаций внутри слушателя событий - PullRequest
0 голосов
/ 20 сентября 2018

Я немного запутался в том, как обновлять связанную коллекцию, используя события доктрины.

Одна сущность связана с другой через ManyToMany.Для лучшего понимания вы можете увидеть примеры ниже (пользователь с заданиями). Цель состоит в том, чтобы: когда статус пользователя будет изменен, его работы также должны быть изменены с прослушивателя событий .

Я уже пробовал preUpdate событие:

public function preUpdate(PreUpdateEventArgs $args)
{
    $entity = $args->getObject();
    foreach ($entity->getJobs() as $job) {
        $entity->getJobs()->removeElement($job);
    }
}

А также onFlush событие:

public function onFlush(OnFlushEventArgs $eventArgs)
{
    $em = $eventArgs->getEntityManager();
    $uow = $em->getUnitOfWork();

    foreach ($uow->getScheduledEntityUpdates() as $entity) {
        foreach ($entity->getJobs() as $job) {
            $entity->getJobs()->removeElement($job);
        }

        $em->persist($entity);
        $uow->recomputeSingleEntityChangeSet(
            $em->getClassMetadata(Job::class),
            $entity
        );
    }
}

Но в случае, когда за пределами прослушивателя был изменен только статус - у пользователя остались те же задания (задания не были изменены из прослушивателя):

$user->setStatus('some-other-status');

Но в случае, когда коллекция была изменена вне слушателя - она ​​работает (задания были изменены со слушателя):

$collection = ... // some new collection of jobs
$user->setJobs(collection);

Любая помощь приветствуется.


Вот фрагменты кода сущностей:

User.php

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity()
 * @ORM\Table()
 */
class User
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $status;

    /**
     * @ORM\ManyToMany(targetEntity="Job")
     * @ORM\JoinTable(name="_user_x_job",
     *     joinColumns={@ORM\JoinColumn(name="user", referencedColumnName="id", onDelete="CASCADE")},
     *     inverseJoinColumns={@ORM\JoinColumn(name="job", referencedColumnName="id", onDelete="CASCADE")}
     * )
     */
    protected $jobs;

    public function __construct()
    {
        $this->jobs = new ArrayCollection();
    }

    ...
}

Job.php:

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity()
 * @ORM\Table()
 */
class Job
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $name;

    ...
}

1 Ответ

0 голосов
/ 20 сентября 2018

Я бы рекомендовал вообще избегать прослушивателей Doctrine для этой задачи.Вместо этого все поведение должно быть смоделировано непосредственно в объекте пользователя: метод setState () также может содержать поведение для удаления задания (й).

Затем обратите внимание на removeOrphans=true параметр отображения доктрины:

По сути, он работает, удаляя Job из коллекции И устанавливая для User значение null.Doctrine обнаружит ваши осиротевшие задания из единицы работы и автоматически удалит их из базы данных при вызове persist($user); flush();

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...