【问题标题】:Doctrine 2.1 - datetime column default valueDoctrine 2.1 - 日期时间列默认值
【发布时间】:2011-12-03 15:49:55
【问题描述】:

有人可以告诉我如何在日期时间列上添加默认值吗?我不能这样做:

protected $registration_date = date("Y-m-d H:i:s", time());

那怎么办?

【问题讨论】:

    标签: php doctrine-orm


    【解决方案1】:

    使用 MySql 和 Symfony 3.4 为我工作。

    ...
    fields:
        start_date:
            type: date
            nullable: false
            options:
                default: '1910-01-01'
                comment: 'The default date is 1910-01-01'
    ...
    

    【讨论】:

      【解决方案2】:

      对于默认值 CURRENT_TIMESTAMP:

           @ORM\Column(name="created_at", type="datetime", options={"default": "CURRENT_TIMESTAMP"})
      

      或者对于旧的 Symfony 版本:

           @ORM\Column(name="created_at", type="datetime", options={"default": 0})
      

      为我工作...但是这仅适用于 MySQL

      【讨论】:

      • 这应该是现在 IMO 的最佳答案,特别是如果您希望表架构本身采用 CURRENT_TIMESTAMP
      • 谢谢。这对我帮助很大。我之前使用过options={"default": "CURRENT_TIMESTAMP"}),通常也可以。但是在我的 postgres db 后面它被转换为 DEFAULT NOW() 这是 postgres 的方式。但是随后一个学说:迁移:差异会将 now() 误解为与 CURRENT_TIMESTAMP 的偏差,并在我每次运行它时创建一个差异文件。但是有了这个解决方案,学说就可以保证一切都是同步的。
      • 很好的答案,而且,IMO,最干净的方式来做到这一点。如果有任何兴趣,我将其翻译为ADD date_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL
      • 值得一提的是,这只适用于 MySQL >= 5.6.5 以下的 MySQL 不支持将 CURRENT_TIMESTAMP 设置为 DATETIME 列的默认值。见stackoverflow.com/a/168832/4735939
      • 这不适用于 mysql:5.7 SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'date_create'
      【解决方案3】:
      @var string @ORM\Column(name="login_at", type="datetime", options={"default" = "CURRENT_TIMESTAMP"})
      

      这会奏效。只是发布以供将来参考。

      【讨论】:

      • 这不起作用:违反完整性约束:1048 列 'login_at' 不能为空
      • @cwhisperer 如果您没有该表的任何数据,上述方法将起作用。意味着如果您已经拥有该列,则必须为每一行向该列添加一些值。否则,请添加允许默认值:nullable=true 在我的情况下,我正在创建一个新表,因此该新表中没有任何数据。
      • 正确,但问题是添加默认值而不是null
      • @cwhisperer,正如我在第一个答案中所说,它将添加默认值作为当前时间戳。但是,如果您尝试将其应用于已存在的具有数据和列的表,那么这将不起作用,就好像有任何行具有空值一样,那么当更改查询运行时,它不会知道要使用哪个时间戳放到那些列的。他们不会吗?我希望这可以消除您可能遇到的困惑
      【解决方案4】:

      如果您想非常精确,也可以使用生命周期回调:

      use Doctrine\ORM\Mapping as ORM;
      
      /**
       * @ORM\HasLifecycleCallbacks
       * ...
       */
      class MyEntity
      {
          /**
           * @ORM\PrePersist
           */
          public function onPrePersistSetRegistrationDate()
          {
              $this->registration_date = new \DateTime();
          }
      }
      

      【讨论】:

      • 我更喜欢这个答案,因为它更清楚 Doctrine 将如何处理它。
      • +1 将最新日期放入记录中。如果记录有两个日期 modified_datetime 和 created_datetime。如果将 modified_datetime 放在构造函数中,created_time 可能会比 modified_datetime 更新。
      • 关于生命周期回调的所有功能的参考:doctrine-orm.readthedocs.org/en/latest/reference/…
      【解决方案5】:

      我认为,为datetime 完成自动填充的最佳方法是这样:

      * @ORM\Column(type="datetime", options={"default"="CURRENT_TIMESTAMP"})
      

      将逻辑放入构造函数不是正确的解决方案,因为设置默认值是SQL 客户端的责任。如果您决定不再使用 ORM - 您将失去业务逻辑。另外,如果使用构造函数,您将无法将默认时间戳添加到 现有行datetime 属性。

      【讨论】:

      • 如下所述"default": 0 更适用于学说迁移。
      【解决方案6】:

      有一个用于自动化此的扩展...

      https://github.com/l3pp4rd/DoctrineExtensions/blob/master/doc/timestampable.md

      /**
           * @var \DateTime
           *
           * @ORM\Column(name="date_added", type="datetime")
           * @Gedmo\Timestampable(on="create")
           */
          private $date_added;
      
          /**
           * @var \DateTime
           *
           * @ORM\Column(name="date_modified", type="datetime")
           * @Gedmo\Timestampable(on="update")
           */
          private $date_modified;
      

      【讨论】:

      • 这需要投票,因为它肯定是最好的方法。
      • @Sc0ttyD 如果您可以通过基本功能达到完全相同的目标,为什么还要使用扩展程序?
      • 不知道 - 不要再使用 PHP,这是 3 年前 :-)
      • @luba 确保数据库兼容性是一种想法。如果一个数据库无法处理将默认值设置为 0 并将其映射到 current_timestamp 或不理解 current_timestamp 怎么办?
      【解决方案7】:

      您将属性映射为 DateTime 类型,然后使用新的 DateTime 实例在构造函数中设置值:

      /**
       * @Entity
       * @Table(name="...")
       */
      class MyEntity
      {
          /** @Column(type="datetime") */
          protected $registration_date;
      
          public function __construct()
          {
              $this->registration_date = new DateTime(); 
          }
      }
      

      这可以作为持久类的构造函数在水合时不调用。

      【讨论】:

      • 我投票赞成这个答案,因为它是纯 PHP 解决方案。其他答案可能:1)需要特殊知识onPrePersistSetRegistrationDate 其中添加HasLifecycleCallbacksPrePersist 注释2)我想设置一个默认值需要我添加第三个库@Gedmo\Timestampable?!! 3) CURRENT_TIMESTAMP 有时不好。例如:当您的脚本服务器在中国但数据库服务器在美国时。 (当然,这不是很常见,但是有这样的情况)
      • @Yarco 视情况而定。当您有一个没有日期时间列的表然后决定添加它时 - 您需要为现有表行填充默认值。在这种情况下,PHP 解决方案将不起作用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-07
      • 2012-11-02
      • 2010-09-15
      • 2020-04-03
      • 1970-01-01
      相关资源
      最近更新 更多