⏱️

Symfony5 x DoctrineでcreatedAt / updatedAtを自動設定

2020/09/30に公開

ほとんど Doctrine2の小ネタ(データベースからエンティティを作る&エンティティの継承編) に記載されている内容と同じだけど、該当記事は公開日が 2014.11.20 なので Symfony 5 でもこれで動きます、というのを書きます。確認したSymfonyのバージョンはv5.1.5。

/**
 * @ORM\Entity(repositoryClass=FooRepository::class)
 * @ORM\HasLifecycleCallbacks
 */
class Foo
{

まず、classの宣言の部分に @ORM\HasLifecycleCallbacks アノテーションを追加。
次に、メソッドとして以下を追加。

/**
 * @ORM\PrePersist
 */
public function setCreatedAtValue()
{
    $this->createdAt = new \DateTimeImmutable();
    $this->updatedAt = new \DateTimeImmutable();
}

/**
 * @ORM\PreUpdate
 */
public function setUpdatedAtValue()
{
    $this->updatedAt = new \DateTimeImmutable();
}

setCreatedAtValue()updatedAt を更新するのが命名的に気持ち悪ければ setUpdatedAtValue() を別メソッドで用意してもOK。

簡単な動作の説明。

@ORM\HasLifecycleCallbacks アノテーションがあるとDoctrineはこのEntityにlifecycle callbackが存在していると認識する。これがないと @ORM\PrePersist@ORM\PreUpdate は呼び出されないので注意。

@ORM\PrePersist はpersistが実行される前(INSERT前)に呼び出されるので、ここで createdAtupdatedAt に現在日時を入れる。

@ORM\PreUpdate は更新される前(UPDATE前)に呼び出されるので、ここで updatedAt に現在日時を入れる。

昔のSymfonyのドキュメントだとTimestampableが一押しだったけれど、Symfony 5でTimestampableはうまく動かないし、無駄に複雑なので、潔くDoctrineのライフサイクルを使った方が良いです。

2021/08/14 追記

Symfony v5.3.6 で make:entity するとtypeのデフォルトが datetime_immutable になっているので、上記の例を \DateTime から \DateTimeImmutable に修正しました。

Discussion