初めに
テーブルにデータを登録/更新する際、登録日や更新日のデータは自動で更新されるようにしたいですよね。DDLでTBLを定義している場合は簡単ですが、ORMの場合は独自の設定が必要になる場合がしばしばあるかと思います。
今回は、Flowで使われているORM「Doctrine」にて、登録日/更新日の自動設定方法を解説します。
環境
技術スタック | バージョン |
---|---|
PHP | 8.2.17 |
Flow | 8.3.8 |
doctrine-orm | 2.19.3 |
TL;DR
実装はこんな感じです。
<?php
namespace Medi\Vega\Domain\Trait;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\HasLifecycleCallbacks
*/
trait CommonTableTrait
{
/**
* @ORM\Column(type="datetime", nullable=false)
* @var \DateTime
*/
protected $createdAt;
/**
* @ORM\Column(type="datetime", nullable=false)
* @var \DateTime
*/
protected $updatedAt;
/**
* @ORM\PrePersist
*/
public function onPrePersist()
{
$this->createdAt = new \DateTime("now");
$this->updatedAt = new \DateTime("now");
}
/**
* @ORM\PreUpdate
*/
public function onPreUpdate()
{
$this->updatedAt = new \DateTime("now");
}
}
ポイントは以下。
- クラスに、
@ORM\HasLifecycleCallbacks
アノテーションを付与 - 登録日と更新日のカラムを定義
- 登録日と更新日に現在時刻を入れるメソッドを用意し、
@ORM\PrePersist
や@ORM\PreUpdate
のアノテーションを付与
複数のTBLで使えるようにtraitで表現しますが、ポイントを押さえれば各Entityでも同じことは可能です。
解説
Doctrineには「イベント管理」という機能があり、今回はそちらを利用しています。
Doctrineは、DBへのデータ登録前後や更新前後など、エンティティが特定のライフサイクルに達した際にトリガーされる処理(Lifecycle Callback)を定義することができます。
処理とトリガーはアノテーションによって紐づけることができ、例でつけている@ORM\PrePersist
と@ORM\PreUpdate
はそれぞれ「登録前」と「登録後」にトリガーされるイベントとして登録されます。
トリガー | タイミング |
---|---|
@ORM\PrePersist |
DBに保存される前のトリガー |
@ORM\PostPersist |
DBに保存された後のトリガー |
@ORM\PreUpdate |
DB更新される前のトリガー |
@ORM\PostUpdate |
更新された後のトリガー |
@ORM\PreRemove |
削除される前のトリガー |
@ORM\PostRemove |
削除された後のトリガー |
@ORM\PostLoad |
読み込まれた後のトリガー |
クラスについている@ORM\HasLifecycleCallbacks
は、このクラスがライフサイクルコールバックを持っているということを明示的に表すためのアノテーションです。これにより、効率的なイベントハンドリングを実現しています。
終わりに
今回は登録日や更新日など、カラムを自動で更新する方法を解説しました。
独自でトリガーを作ったり、エンティティ外からトリガーする方法もあるみたいなので、今度試してみようと思います。
ここまで読んでいただきありがとうございました!