实体信息更改时创建新的实体对象

时间:2018-04-12 03:42:35

标签: php symfony doctrine

我有3个实体:资产,用户,日志

关系是:

  • 资产可以拥有多个用户,用户可以拥有多个资产。所以这是一个多对多的关系。
  • 日志只能有1个资产,资产可以包含多个日志。因此,这是与资产作为拥有方的一对多关系。

所以场景是这样的:

  • 如果我在应用程序端向用户分配资产,我应该 得到一个 new 这样的日志(log_id,asset_id,资产已经 分配给user_fullname)
  • 如果我将用户分配到资产上 应用程序方面,我应该得到一个 new 这样的日志(log_id, asset_id,资产已分配给user_fullname)
  • 如果我在应用程序端向用户删除资产,我应该 得到一个 new 这样的日志(log_id,asset_id,资产已经 从user_fullname中删除)
  • 如果我将用户移到了资产上 应用程序方面,我应该得到一个 new 这样的日志(log_id, asset_id,资产已从user_fullname中删除)

我在资产实体上尝试过这样做:

    public function addUser(\AppBundle\Entity\User $user)
{
    $this->users[] = $user;
    $this->getDoctrine()->getManager()->persist(new Log($this,
                    "Asset has been added to" . $user->getFullname()
                    ,$this->getUser()));
    $this->getDoctrine()->getManager()->flush();
    return $this;
}

这给了我一个错误,即找不到EM,我做了一些研究,发现这是不好的做法。

所以我尝试了这个:

$oldAsset = $this->getDoctrine()->getManager()->getRepository('AppBundle:Asset')->findOneById($asset->getId());

        if ($assign_form->isSubmitted() && $assign_form->isValid()) {


            foreach($asset->getUsers() as $user)
                if(!$oldAsset->getUsers()->contains($user))
                    $this->getDoctrine()->getManager()->persist(new Log($asset,
                        "Asset has been assigned to " . $user->getFullname()
                        ,$this->getUser()));

            foreach($oldAsset->getUsers() as $user)
                if(!$asset->getUsers()->contains($user))
                    $this->getDoctrine()->getManager()->persist(new Log($asset,
                        "Asset has been removed from " . $user->getFullname()
                        ,$this->getUser()));

            $this->getDoctrine()->getManager()->flush();

            return $this->redirectToRoute('asset_show', array('id' => $asset->getId()));
        } 

即使在我手动冲洗它之前,它还没有起作用,它会更新"来自数据库的实体,因此旧资产和新资产之间没有差异。奇怪的是,在整个方法完成之前,一旦出现错误,编辑就无法通过。

我知道我在这里遗漏了一些东西,也许有一种我不知道的方法会使这种情况成为可能。

1 个答案:

答案 0 :(得分:2)

这可以通过事件监听器(Symfony docDoctrine doc)来实现:

<强>的Acme \监听\ UserListener.php:

<?php

namespace Acme\Listener;


use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\EntityManagerInterface;
use Acme\Entity;

class UserListener {

    /**
     * @ORM\PostUpdate()
     */
    public function postUpdate(Entity\User $user, LifecycleEventArgs $event) {

        $em = $event->getEntityManager();

        $log = new Entity\Log(...);

        // ...

        $em->persist($log);
        $em->flush();
    }
}

将监听器注册为服务,标记为doctrine.event_listener

<强> services.yml:

services:
    # ...

    Acme\EventListener\UserListener:
        arguments: [ '@doctrine.orm.entity_manager' ]
        tags:
            - { name: doctrine.event_listener }

现在,只要刷新了一个更改了由实体管理器管理的User对象的操作,就应该调用监听器的postUpdate方法。

对于下一位,我假设您已将User配置为与Asset的关系中的拥有方。

如果您正确设置了实体(意味着在更改关系时同步更新反面,可以在Doctrine docsthis gist中找到更多信息),则听众不仅应该在向/从用户分配/删除资产时调用,还要在向资产分配/从资产中删除用户时调用。