Doctrine - 向实体添加默认时间戳,如 NOW()

问题描述 投票:0回答:8

遵循 Doctrine 指南,我了解如何为实体设置默认值,但如果我想要日期/时间戳怎么办?

我的问题是我的数据库在字段上有默认值 NOW(),但是当我使用 Doctrine 插入记录时,值是 null 或空白,但其余的插入发生了。

而且由于 Doctrine 说将默认值声明为 const,这也会产生一个问题。

建议?

php postgresql symfony doctrine-orm entities
8个回答
27
投票

好的,我找到了解决方案:

prePersist
选项就是我正在做的。

确保在注释中定义

<?php

/** @Entity 
 *  @HasLifecycleCallbacks 
 */
class User

这是他们提供的功能示例

/** 
 *  @PrePersist 
 */
public function doStuffOnPrePersist()
{
    $this->createdAt = date('Y-m-d H:i:s');
}

如果你像我一样使用 ORM

<?php

/** @ORM\Entity 
 *  @ORM\HasLifecycleCallbacks 
 */
class User

这是他们提供的功能示例

/** 
 *  @ORM\PrePersist 
 */
public function doStuffOnPrePersist()
{
    $this->createdAt = date('Y-m-d H:i:s');
}

9
投票

根据我的经验,最好将所有内容都放在实体中,而不是试图强制数据库绕过 ORM。

<?php
namespace Phill\PaffordBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
 * Stack
 * @ORM\Table()
 */
class Stack
{
  /**
   * @var integer
   * @ORM\Column(type="integer")
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  private $id;

  /**
   * @var \DateTime
   * @ORM\Column(type="datetime")
   */
  private $startDate;

  public function __construct()
  {
    $this->startDate = new \DateTime();
  }

}

7
投票

为了准确地获得

NOW()
,您可以扩展
Doctrine\DBAL\Types\DateTimeType

其他方法:

class DateTimeNow
{
    public function format() 
    {
        return 'NOW()';
    }
}

然后您可以使用

$entity->setFieldDatetime(DateTimeNow())
代替
$entity->setFieldDatetime(new Datetime())

注意:方法
format()
由Doctrine自动调用。


3
投票

试试这个:

/**
 * @var \DateTime
 *
 * @Column(name="created", type="datetime", nullable=false)
 */
private $created;

function __construct()
{
    $this->created = new \DateTime();
}

您分配给

$value
字段的任何
created
都必须能够处理此调用:

$value->format('Y-m-d H:i:s');

参见相关学说代码行

经测试可与 Doctrine 2.5.4 配合使用

注意:上面的方法在创建时有效,但默认情况下在更新时无效 - 当您进行更新或查看

created
 时,您必须手动将 
new \DateTime()
 属性设置为 
doStuffOnPrePersist

/** @PrePersist */
public function doStuffOnPrePersist()
{
    $this->created = date('Y-m-d H:i:s');
}

3
投票
#[ORM\Column(type: 'datetime_immutable', options: ['default' => 'CURRENT_TIMESTAMP'])]
    private $createdAt;

    #[ORM\Column(type: 'datetime_immutable', options: ['default' => 'CURRENT_TIMESTAMP'], columnDefinition: "DATETIME on update CURRENT_TIMESTAMP")]
    private $modifiedAt;

这是我发现的,我能够得到“ON UPDATE CURRENT_TIMESTAMP()”,但是该列变为可为空,在我看来这是一个更好的权衡。


1
投票

您可以使用 TimestampableEntity Trait 在实体中自动创建created_at和updated_at字段;

首先安装原则扩展;

composer require gedmo/doctrine-extensions

其次将特征添加到您的实体类中;

use Gedmo\Timestampable\Traits\TimestampableEntity;

    /**
     * @ORM\Entity(repositoryClass="App\Repository\ProjectRepository")
     */
    class Project
    {
        use TimestampableEntity;

0
投票

对于 PostgreSQL,您应该能够为字段传递

now
的字符串值来获取要运行的时间戳。


0
投票

我的方法是让数据库将日期时间字段配置为

CURRENT_TIMESTAMP()
。不使用 Doctrine 的
PrePersist
或在 PHP 中手动调用该设置器的原因是我们的数据库(我的意思是数据)与其他项目共享。这些项目甚至没有使用 Doctrine,实际上这些甚至都不是 PHP 项目,因此我们希望将设置日期时间的责任转移到数据库,集中在一个地方。

但正如作者指出的,是的,Doctrine 在刷新持久实体时将

null
值作为日期时间传递给数据库存在问题,这给出了以下错误:

违反完整性约束:1048 列“createdAt”不能为空

解决这个问题的方法是设置

insertable: false
(默认为
true
):

#[ORM\Column(
    name: "createdAt",
    type: "datetime",
    nullable: false,
    insertable: false,
    options: ["default" => "CURRENT_TIMESTAMP"]
)]
private \DateTime $createdAt;
© www.soinside.com 2019 - 2024. All rights reserved.