こんにちは。これもフレームワーク標準でよいのでは?只野です。
業務系のシステム作ってるとよくある要件があります。
“テーブルのレコード登録者、更新者を持ちたい”
これは業務システムで不具合やデータがおかしい時に誰がいつどのデータを触ったか特定できるようにする要件です。
正確には履歴を取らないと全てのデータを追うことはできませんが、簡易的に追えるようにするだけでシステムの運用は随分と違います。
そんで「Laravel」の機能でないかと調べたら、これがないんですね~
登録日、更新日を自動設定してくれる機能はあるのですが、登録者、更新者を自動設定する機能はないんですね。
これは必ずしもログイン機能を搭載したシステムが作成されるわけではないからですかね?
そんな感じで「Laravel」の標準では対応してくれないので、自分達で実装する必要があります。
しょうがないので実装方式を検討した結果、下記の方式で簡易的ですが、共通で登録者、更新者を設定する仕組みが作れそうです。
仕様!
- Model用共通Traitの作成
- 各テーブルに共通項目として登録者、更新者を追加
実装ソース構成!
- {ドキュメントルート}\app\Traits\ModelTrait.php
「Model」の共通処理はクラス化して継承するか悩みましたが、「Laravel」フレームワークの標準だと「Trait」が様々な場所で使われ、「Model」も例外ではありません。何なら「php artisan make:model」コマンドで出力した「Model」は、出力状態で「Trait」がソース内に組み込まれています。
この事から「Model」を独自に共通クラスにすると色々弊害だ置きそうだったので、「Trait」の仕組みで実装することにしました。
1:実装!
- {ドキュメントルート}\app\Traits\ModelTrait.php
<?php namespace App\Traits; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Auth; /** * モデルTrait * モデルで利用する共通メソッドを提供します。 */ trait ModelTrait { /** * 保存前処理です。 * ※当メソッドはupdate後にもフレームワークの処理で呼び出されます。 */ public function save(array $options = []) { //■登録前処理 Log::debug($this->table.'保存しました。'); if (Auth::check()) { if (empty($this->id)) { $this->created_user_id = Auth::id(); } $this->updated_user_id = Auth::id(); } parent::save($options); } /** * 更新前処理です。 */ public function update(array $attributes = [], array $options = []) { //■更新前処理 Log::debug($this->table.'更新しました。'); if (Auth::check()) { $this->updated_user_id = Auth::id(); } parent::update($attributes, $options); } /** * 削除前処理です。 */ public function delete(array $attributes = [], array $options = []) { //■削除前処理 Log::debug($this->table.'削除しました。'); if (in_array('Illuminate\Database\Eloquent\SoftDeletes', class_uses(get_class($this)))) { // 論理削除の場合、更新者設定 $this->update(); } parent::delete($attributes, $options); } }
単純に「Model」クラスの各BD操作メソッドをオーバーライドするメソッドを実装するだけです。オーバーライドメソッドの最後に元のメソッドを呼び出すところが重要です。
今回は各メソッドの先頭でログ出力していますが、実際の実装では必要ありません。
「delete」メソッドで「update」を実行しているのは「laravel」の標準機能で「softDelete」というデータの論理削除機能があるのですが、この時にも更新者を設定したかったからです。
2:利用方法!
共通処理を実装したい「Model」クラスに作成した「Trait」を設置するだけです。
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; // 1:ここから use App\Traits\ModelTrait; // 1:ここまで class Company extends Model { use HasFactory; // 2:ここから use ModelTrait; // 2:ここまで }
これで「Model」が提供する「save」、「update」、「delete」メソッドを利用した際にまず、独自に実装したメソッドが実行されるようになります。
あとは登録者、更新者を設定するカラムをテーブルに追加するだけです。今回は下記カラムを共通カラムとして、テーブルに定義しています。
論理名:登録ユーザーID 物理名:created_user_id 型:bigint unsigned 初期値:0 論理名:更新ユーザーID 物理名:updated_user_id 型:bigint unsigned 初期値:0
初期値指定しているのはバッチ処理などでログインユーザー情報がない時に作成されたデータを特定しやすいように設定しています。
本日はこの辺で