php - Doctrine - 更新事件监听器内的多对多关联

标签 php symfony doctrine-orm

我对如何使用学说事件更新相关集合有点困惑。

一个实体通过多对多(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);

欢迎任何帮助。


以下是实体的代码片段:

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

    ...
}

作业.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;

    ...
}

最佳答案

我建议在此任务中完全避免 Doctrine 事件监听器。相反,整个行为应该直接在用户实体中建模:setState() 方法还可以保留删除作业的行为。

然后寻找removeOrphans=true学说映射选项:

基本上它的工作原理是删除 Job从集合中并设置其 User为空。 Doctrine 将从工作单元中检测到您的孤立作业,并在调用 persist($user); flush(); 时自动从数据库中删除它们。

关于php - Doctrine - 更新事件监听器内的多对多关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52422588/

相关文章:

php - cakephp中的mysql语句之间

php - 为 iTunes 制作播客 RSS 提要

php - 添加到列的数值

php - 教义2 : Lazy loading fails and I have to re-initialize the class

php - $_POST、$_GET 和 $_REQUEST 之间有什么区别?

php - Doctrine2 Multiple Join 适用于 createQuery 但不适用于 queryBuilder

php - 如何在 Symfony 2 中使用 ajax 登录?

php - 如何阻止 Symfony 记录 Doctrine 的 sql 查询?

php - 学说查询生成器 : how to do a query with inner joins conditions

doctrine - 如何在表格便捷方法中指定HYDRATE_ARRAY?