如何在持久化后更新实体字段(例如在postPersist方法中)?

时间:2013-12-13 09:26:23

标签: symfony doctrine-orm symfony-2.3

我有一个带有代码字段的实体任务,需要使用其父名称的第一个字母(实体项目)加上自己的id字段填充,但是在实体持久保存到数据库之前我没有id,并且在postPersist方法中,我无法更改实体Task,因为这些更改不会被保留。

这是我的代码:

class Project
{

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="name", type="string", length=255)
 */
private $name;
}



class Task
{

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="code", type="string", length=255)
 */
private $code;

/**
 * @ORM\ManyToOne(targetEntity="Project", inversedBy="tasks")
 * @ORM\JoinColumn(name="project_id", referencedColumnName="id")
 */
private $project;
}

任何人都有任何想法?

提前致谢。

2 个答案:

答案 0 :(得分:4)

我用听众解决了这个问题。

我在MyBundle-> Resources-> config-> services.yml文件中写道:

parameters:
    task.listener.class: MyBundle\EventListener\TaskListener

services:
    task.listener:
        class: %task.listener.class%
        tags:
            - { name: doctrine.event_listener, event: postPersist }

在MyBundle-> EventListener-> TaskListener.php中:

<?php
namespace MyBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\OnFlushEventArgs;

use MyBundle\Entity\Task;

class TaskListener
{
    public function postPersist(LifecycleEventArgs $args)
    {
        $entity     = $args->getEntity();
        $em         = $args->getEntityManager();

        if ($entity instanceof Task) {
            $entity->setCode(substr($entity->getProject()->getName(), 0, 1).$entity->getId());

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

这样,当实体实例在数据库中有id时,我使用postPersist事件来设置代码。

我希望这些信息对某人有用。

感谢。

答案 1 :(得分:0)

您的设计不尊重数据库规范化

在我看来,你想要达到的目标不尊重Database Normalization。 您不会因此设计而尊重1NF的规则。

以下是1NF规则:

- The table must contain only atomic fields
- Eliminate redundant information.

这篇伟大的文章应该可以帮助你理解什么是数据库规范化,什么是1NF等...以及为什么尊重这些规则很重要: Demystified: Database Normalization

你想:

  

具有代码字段的实体任务,需要使用   其父母名称(实体项目)的第一个字母加上自己的ID   字段

信息在代码字段中是多余的。如果产品名称发生变化怎么办?在这种情况下你需要更新任务代码吗?这段代码必须是唯一的吗?为什么要存储已经可用的两倍?

你能做什么:

解决方案1 ​​ 在您的情况下,为什么不简单地使用id字段?

解决方案2 为什么不在没有将代码存储在数据库中的情况下使用getter?

解决方案3 为产品创建一个代码字段(您提到了一个字母,所以这可能并非对所有人都是唯一的你的产品)。我会选择3封信。例如:

iPad : ipa
iPhone : iph
iMac: ima

您可以决定是否希望此代码是唯一的。因此,如果需要,请使用UniqueEntity字段类型验证唯一性。然后,您可以使用“产品代码”+“id”制作代码。 如上所述,我不会在数据库中创建“任务代码”字段以避免破坏1NF规则。你只需要一个获得简单组合“产品代码”+“id”的getter。