はじめに
基幹システムをリプレイスする際、別のシステムが基幹システムと同じデータベースを参照・更新している箇所がある為、DB構造の変更に制約があった。
その制約の以下のようなタイムスタンプ系のカラムがありました。
- create_user_code
- update_user_code
- create_datetime
- update_datetime
レコードを更新するたびに値を入れる処理を書くのは面倒だ。
解決策 抽象モデルクラスの作成
こんな感じの抽象モデルクラスとモデルイベントのオブザーバーを作成した。
該当のモデルクラスに対して、この抽象モデルを継承させるだけでOK
使い方
// 各モデルはこれを継承するだけ
class Post extends AbstractAuditableModel
{
// タイムスタンプのカラム名とか、作成者・更新者の処理とか
// 全部親クラスで面倒見てくれる
}
抽象モデル
abstract class AbstractAuditableModel extends Model
{
use AuditableObservable;
public const CREATED_AT = 'create_datetime';
public const UPDATED_AT = 'update_datetime';
final public function createUser(): BelongsTo
{
return $this->belongsTo(User::class, 'create_user_code', 'user_code');
}
final public function updateUser(): BelongsTo
{
return $this->belongsTo(User::class, 'record_user_code', 'user_code');
}
}
トレイト
trait AuditableObservable
{
public static function bootAuditableObservable(): void
{
static::observe(AuditableObserver::class);
}
}
オブザーバー
class AuthorObserver
{
public function creating(AbstractAuthorModel $model): void
{
$model->create_user_code = auth()->user()->user_code
$model->update_user_code = auth()->user()->user_code;
}
public function updating(AbstractAuthorModel $model): void
{
...
}
public function saving(Model $model)
{
...
}
public function deleting(Model $model)
{
...
}
}
まとめ
百テーブルぐらいが対象だったので、とても役に立った👍
が、ぶっちゃけ抽象クラスじゃなくてもTraitだけで良かった感も。