在我的Symfony2 2/Doctrine2webapp中有一个User实体。这个用户有一个属性last_updated来标识最近的时间,任何事情都变了。我在数据库中将这个属性设置为NOT NULL。到现在为止还好。
我认为在数据库中创建一个SQL触发器是一个很好的实践,它将这个last_updated设置为在每个INSERT或UPDATE上的NOW()。所以你不必在你的申请中关心这个问题。这就是我所做的,我在我的数据库中实现了这个触发器。
但是如果我现在在我的应用程序中创建一个用户
$user = new User();
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();我收到Symfony的一条错误消息:
使用params
'INSERT INTO User (username, ..., last_updated) VALUES (?, ..., ?)'执行["johndoe", ..., null]:时发生异常 SQLSTATE23000:完整性约束违反: 1048列'last_updated'不能为空
问题很明显: Symfony试图使用参数INSERT-statement为last_updated向数据库发送null,这是不允许的--因为这个属性可能不是null。
我很快就能想到两个解决办法:
last_updated字段从实体描述中删除。然后Symfony将不会尝试将任何内容传递给该列的数据库,并且触发器将设置适当的值。但我不认为这是一个好方法,因为只要我尝试更新db模式(doctrine:schema:update --force),我就会释放last_updated-column。$user->setLastUpdated(new \DateTime())和flush()之前执行persist()。但这将尽量减少在我的数据库中使用触发器的好处,以避免在我的应用程序中关心它。有没有办法让Symfony/Doctrine知道我的数据库上有一个触发器在运行?如果不是,(如何)我可以连接到Symfony/Doctrine来实现一个适当的解决方案?
发布于 2013-08-22 20:20:42
若要引用google组对此问题的答复:
数据库端代码(如触发器和函数)倾向于破坏使用ORM (如Propel或Doctrine )开发软件的好处,因为使用ORM的最大优势之一是数据库不可知论。通过拥有数据库端触发器和函数,您将自己绑定到数据库上,因此使用ORM几乎没有什么好处。-GarethMc
为此,最好像Faery建议的那样使用生命周期回调。一个简单的函数将处理更新该字段,这样如果您决定在将来更改数据库,就不必担心它。
//In Your Entity File EX: SomeClass.php
/**
* @ORM\Entity
* @ORM\HasLifecycleCallbacks()
*/
class SomeClass
{
....
/**
* @ORM\PrePersist()
* @ORM\PreUpdate()
*/
public function prePersistPreUpdate()
{
$this->last_modified = new \DateTime();
}
}还请参阅生命周期回调的引用。
在您的示例中,您将向用户实体类添加生命周期回调函数和注释。SomeClass只是一个示例类,它表明生命周期回调不仅仅对用户实体有好处。
发布于 2015-06-09 13:56:33
另一个(更容易和更广泛的)选项是使用Gedmo的Timestampable原则扩展。这样,您可以简单地注释实体字段,以便在create或update上加盖时间戳。
示例:
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
class MyEntity
{
...
/**
* @var \DateTime $lastUpdated
*
* @Gedmo\Timestampable(on="update")
* @ORM\Column(name="last_updated", type="datetime")
*/
private $lastUpdated;
...
}https://stackoverflow.com/questions/18377690
复制相似问题