在 Doctrine 中为 updated_at、created_at 自动取值
Posted
技术标签:
【中文标题】在 Doctrine 中为 updated_at、created_at 自动取值【英文标题】:Automatic values for updated_at, created_at in Doctrine 【发布时间】:2013-06-23 16:47:42 【问题描述】:我想让我的Doctrine 实体中的字段updated_at
和created_at
自动更新。
在 Ruby on Rails 模型中有 2 个字段:updated_at
和 created_at
。
描述可以在这里找到:http://guides.rubyonrails.org/migrations.html#migration-overview:
timestamps 宏添加了两列,created_at 和 updated_at。如果存在这些特殊列,则它们会由 Active Record 自动管理。
我可以在 Doctrine 2 中启用类似的功能吗?
【问题讨论】:
【参考方案1】:-
您可以在
__construct
方法中调用$this->setCreatedAt(new \DateTime())
。
您可以使用Life Cycle Callbacks
/**
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function updatedTimestamps(): void
$this->setUpdatedAt(new \DateTime('now'));
if ($this->getCreatedAt() === null)
$this->setCreatedAt(new \DateTime('now'));
并且不要忘记添加到实体类符号中:
@ORM\HasLifecycleCallbacks
【讨论】:
在此处获取 OOP 示例-gist.github.com/lelledaniele/be67e03b51e04ab9f9b04b985ccd94e2 3.在构造函数中使用:$this->publishedAt = new \DateTime();
和 $this->updatedAt = new \DateTime();
@VladimirCh 即使实体中没有任何其他内容被更新,也会设置 updatedAt。
@marcguyer 不正确,因为构造函数只会在第一次创建时被教义调用。
'now' 不需要 new \DateTime('now')
,因为它是默认值【参考方案2】:
如果您想单独处理它们,这是另一种选择。
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="person")
* @ORM\HasLifecycleCallbacks
*/
class Person
..........
/**
* @var datetime $created
*
* @ORM\Column(type="datetime")
*/
protected $created;
/**
* @var datetime $updated
*
* @ORM\Column(type="datetime", nullable = true)
*/
protected $updated;
/**
* Gets triggered only on insert
* @ORM\PrePersist
*/
public function onPrePersist()
$this->created = new \DateTime("now");
/**
* Gets triggered every time on update
* @ORM\PreUpdate
*/
public function onPreUpdate()
$this->updated = new \DateTime("now");
..........
【讨论】:
很好的答案,但如果您想按此字段排序,updated_at
在第一次更新之前获得空值这一事实可能会很痛苦。
@El_Matella 您只需更改onPrePersist()
函数,使其同时设置created
和updated
。如果您之前在生产环境中没有这样做,也可以轻松地在数据库中修复。
是的,我就是这么做的 :)
如何使用 Yml 文件在 createdAt 字段中插入当前日期时间?
非常好。对于未来的用户,不要忘记在类注释中添加@ORM\HasLifecyleCallbacks(这会节省我一些时间)。【参考方案3】:
对我来说最方便的解决方案是StofDoctrineExtensionsBundle 的Timestampable
功能。
简单的配置,之后您可以通过添加两个简单的annotations
来自动填写Entity
的createdAt
和updatedAt
字段,例如:
@Gedmo\Mapping\Annotation\Timestampable(on="create")
和/或
@Gedmo\Mapping\Annotation\Timestampable(on="update")
例如
/**
* @var \DateTime
* @Gedmo\Mapping\Annotation\Timestampable(on="create")
* @Doctrine\ORM\Mapping\Column(type="datetime")
*/
protected $createdAt;
/**
* @var \DateTime
* @Gedmo\Mapping\Annotation\Timestampable(on="update")
* @Doctrine\ORM\Mapping\Column(type="datetime")
*/
protected $updatedAt;
纯php
中没有任何冗余代码。
【讨论】:
如果您已经使用 StofDoctrineExtensions(可能是我们大多数人),这是最好的解决方案。应该注意的是,您需要启用时间戳:symfony.com/doc/master/bundles/StofDoctrineExtensionsBundle/… 使用 Symfony 4.0+composer require stof/doctrine-extensions-bundle
安装(使用 Flex)
我在 symfony Flex 中使用这种方法,对我来说唯一缺少的部分是我必须更新 ./config/bundles.php
以包含 Stof 包:Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle::class => ['all' => true],
【参考方案4】:
您也可以将其实现为 trait - 像这样:
<?php
namespace App\Entity\Traits;
use DateTime;
use DateTimeInterface;
use Exception;
/**
* Trait TimeStampableTrait
* @package App\Entity\Trait
*/
trait TimeStampableTrait
/**
* @ORM\Column(type="datetime")
*/
private $createdAt;
/**
* @ORM\Column(type="datetime")
*/
private $updatedAt;
/**
* @return DateTimeInterface|null
* @throws Exception
*/
public function getCreatedAt(): ?DateTimeInterface
return $this->createdAt ?? new DateTime();
/**
* @param DateTimeInterface $createdAt
* @return $this
*/
public function setCreatedAt(DateTimeInterface $createdAt): self
$this->createdAt = $createdAt;
return $this;
/**
* @return DateTimeInterface|null
*/
public function getUpdatedAt(): ?DateTimeInterface
return $this->updatedAt ?? new DateTime();
/**
* @param DateTimeInterface $updatedAt
* @return $this
*/
public function setUpdatedAt(DateTimeInterface $updatedAt): self
$this->updatedAt = $updatedAt;
return $this;
/**
* @ORM\PrePersist()
* @ORM\PreUpdate()
*/
public function updateTimestamps(): void
$now = new DateTime();
$this->setUpdatedAt($now);
if ($this->getId() === null)
$this->setCreatedAt($now);
将此特征添加到您的实体(不要忘记@ORM\HasLifecycleCallbacks()
符号):
<?php
namespace App\Entity;
use App\Entity\Traits\TimeStampableTrait;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\MyEntityRepository")
* @ORM\HasLifecycleCallbacks()
*/
class MyEntity
use TimeStampableTrait;
【讨论】:
【参考方案5】:我建议使用可时间戳特征
https://symfonycasts.com/screencast/symfony4-doctrine/timestampable
use Gedmo\Timestampable\Traits\TimestampableEntity;
class Article
use TimestampableEntity;
将自动添加所有适当的功能
【讨论】:
以上是关于在 Doctrine 中为 updated_at、created_at 自动取值的主要内容,如果未能解决你的问题,请参考以下文章