我有一个带有代码字段的实体任务,需要使用其父名称的第一个字母(实体项目)加上自己的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;
}
任何人都有任何想法?
提前致谢。
答案 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。