8

我的 Symfony2/Doctrine2 webapp 中有一个User实体。这个用户有一个属性last_updated来标识最近的时间,什么都改变了。我将此属性设置为NOT NULL在我的数据库中。到目前为止,一切都很好。

我认为在数据库中创建一个 SQL 触发器是一种很好的做法,它将它设置last_updatedNOW()every INSERTor UPDATE。所以你不必在你的应用程序中关心这个。这就是我所做的,我在我的数据库中实现了这个触发器。

但是如果我现在在我的应用程序中创建一个用户

$user = new User();
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();

我收到 Symfony 的错误消息:

'INSERT INTO User (username, ..., last_updated) VALUES (?, ..., ?)' 使用参数执行时发生异常["johndoe", ..., null]:

SQLSTATE [23000]:违反完整性约束:1048 列'last_updated'不能为空

问题很明显:Symfony 正在尝试INSERT使用参数nullfor向数据库触发 - 语句last_updated,这是不允许的 - 因为该属性可能不为空。

我可以很快想到两种解决方法:

  • 一种解决方法是将last_updated字段从实体描述中取出。然后 Symfony 不会尝试为此列向数据库传递任何内容,触发器会设置适当的值。但我认为这不是一个好方法,因为一旦我尝试更新 db 模式 ( doctrine:schema:update --force),我就会失去我的last_updated-column。
  • 另一种解决方法:只需$user->setLastUpdated(new \DateTime())在 ipersist()flush(). 但这会最大限度地减少在我的数据库上使用触发器的优势,以避免在我的应用程序中关心它。

有什么方法可以让 Symfony/Doctrine 知道我的数据库上有一个触发器在运行?如果没有,(如何)我可以使用 Symfony/Doctrine 来实施适当的解决方法?

4

2 回答 2

15

引用 google 组对这个问题的回答:

数据库端代码(例如触发器和函数)往往会破坏使用像 Propel 或 Doctrine 这样的 ORM 开发软件的好处,因为使用 ORM 的最大优势之一是与数据库无关。通过拥有数据库端触发器和函数,您将自己绑定到数据库,因此使用 ORM 几乎没有任何好处。-加雷斯麦克

https://groups.google.com/forum/#!topic/symfony-users/MH_ML9Dy0Rw

为此,最好按照 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 只是一个示例类,它表明生命周期回调不仅仅适用于您的 User 实体。

于 2013-08-22T20:20:42.663 回答
5

另一个(更简单、更通用)的选择是使用TimestampableGedmo 的 Doctrine 扩展。通过这种方式,您可以简单地注释您的实体字段,以便在创建或更新时添加时间戳。

例子:

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://packagist.org/packages/gedmo/doctrine-extensions

于 2015-06-09T13:56:33.567 回答