Help us understand the problem. What is going on with this article?

Laravel Auditingでデータベースの変更を監視する

『誰がいつ、データをいじったか知りたい』というデータの監視が必要な時に、Laravel Auditingが便利です。

概要

Laravel Auditingはデータベース上の指定した監視対象のテーブルに追加・更新・削除などの変更が行われた場合に、誰がどのような変更を行ったかを自動でログ保存するパッケージです。

outline.001.jpeg

インストール & 設定

インストール

composerで行います。

composer require owen-it/laravel-auditing

設定

インストール後、config/app.phpにプロバイダーを追加します。

config/app.php
'providers' => [
+    OwenIt\Auditing\AuditingServiceProvider::class,
],

追加したら、Laravel Auditing用の設定ファイルを作成するために以下のコマンドを実行します。

php artisan vendor:publish --provider "OwenIt\Auditing\AuditingServiceProvider" --tag="config"

実行すると、config/audit.phpというファイルが作成されます。特にカスタマイズする必要がなければそのまま、データベースのマイグレーションファイルを以下のコマンドで作成します。

php artisan vendor:publish --provider "OwenIt\Auditing\AuditingServiceProvider" --tag="migrations"

実行すると、auditsテーブルを作成するためのdatabase/migrations/yyyy_mm_dd_nnnnnn_create_audits_table.phpというファイルが作成されます。作成後にマイグレーションしてauditsテーブルを作成します。

php artisan migrate

監視

基本的な設定

設定が完了したら、監視したいデータのモデルに追記します。例えばitemsテーブルのデータを監視したい場合は、

app/Item.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
+ use OwenIt\Auditing\Contracts\Auditable;
+
+ class Item extends Model implements Auditable
- class Item extends Model
{

+    use \OwenIt\Auditing\Auditable;

ちょっとややこしいのですが、インターフェイスはOwenIt\Auditing\Contracts\Auditable、traitは\OwenIt\Auditing\Auditableを指定します。これらを追記するだけで、監視対象となります。

実際に監視

では、このテーブルに対して新規登録・変更・削除を行ってみましょう。これらを実行すると、auditsテーブルに以下のようなデータが追加されます。

id user_type user_id event auditable_type auditable_id old_values new_values url ip_address user_agent tags created_at updated_at
1 NULL NULL updated App\Item 2 {"name":"\u8ffd\u52a01"} {"name":"\u8ffd\u52a02"} http://localhost:8000/items/2 127.0.0.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Safari/605.1.15 NULL 2020-03-23 12:20:34 2020-03-23 12:20:34
2 App\User 1 created App\Item 3 [] {"name":"\u307b\u3052","stock":"10","id":3} http://localhost:8000/items 127.0.0.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Safari/605.1.15 NULL 2020-03-23 12:21:39 2020-03-23 12:21:39
3 App\User 1 deleted App\Item 3 {"id":"3","name":"\u307b\u3052","stock":"10"} [] http://localhost:8000/items/3 127.0.0.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Safari/605.1.15 NULL 2020-03-23 12:51:57 2020-03-23 12:51:57

監視対象のデータは以下のような内容が蓄積されます。

フィールド名 蓄積内容
id 監視データのID
user_type ユーザモデルのクラス名
user_id ユーザID
event 実行したイベント
auditable_type 更新したデータモデルのクラス名
auditable_id 更新したデータのID
old_values 更新前のデータ
new_values 更新後のデータ
url 実行されたURL
ip_address IPアドレス
user_agent ユーザエージェント
tags タグ
created_at 作成日時(= データが更新された日時)
updated_at 更新日時

あまりないと思いますが、ログインせずにデータを更新した場合は、user_type, user_idがNULLになります。

監視データの取得

監視データは監視対象のモデルに関連しています。

<?php

$item = Item::find(1);

// 該当データの全ての監視データ
$audits = $item->audits;

// 該当データの最初の監視データ
$first = $item->audits()->first();

// 該当データの直近の監視データ
$latest = $item->audits()->latest()->first();

// 該当データの監視データのID指定
$audit = $item->audits()->find(1);

監視データもEloquentモデルなので、直接取得できます。

<?php

use OwenIt\Auditing\Models\Audit;

// 全件取得
$audits = Audit::all();

// ID指定
$audit = Audit::find(1);

カスタマイズ

コンソールコマンドでの実行も監視したい

デフォルトでは、コンソールコマンドやジョブの更新は監視対象外となっています。監視したい場合は、config/audit.phpで設定を変更します。

config/audit.php
-    'console' => false,
+    'console' => true,

監視するフィールドを絞り込みたい

デフォルトでは、登録・更新日時以外を対象とします。監視するフィールドを絞り込みたい場合は監視対象モデルに設定を追記します。

app/Item.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use OwenIt\Auditing\Contracts\Auditable;

class Item extends Model implements Auditable
{
    use \OwenIt\Auditing\Auditable;


+    protected $auditInclude = [
+        'name',
+    ];

逆に除外したい場合は、$auditExcludeに指定することで、除外できます。

蓄積するデータを変えたい

蓄積するデータをカスタマイズしたい場合は、独自のResolverを作成します。Laravel Auditingでは以下のResolver用インターフェイスが用意されています。

インターフェイス 概要
OwenIt\Auditing\Contracts\IpAddressResolver IPアドレス用I/F
OwenIt\Auditing\Contracts\UrlResolver URL用I/F
OwenIt\Auditing\Contracts\UserAgentResolver ユーザエージェント用I/F
OwenIt\Auditing\Contracts\UserResolver ユーザモデル用I/F

これらを実装することで、蓄積するデータを変えることができます。

app/resolvers/IpAddressResolver.php
<?php
namespace App\Resolvers;

use Illuminate\Support\Facades\Request;

class IpAddressResolver implements \OwenIt\Auditing\Contracts\IpAddressResolver
{
    /**
     * {@inheritdoc}
     */
    public static function resolve(): string
    {
        return Request::header('HTTP_X_FORWARDED_FOR', '0.0.0.0');
    }
}

独自Resolverはconfig/audit.phpで設定することで反映されます。

config/audit.php
return [
    'resolver' = [
        'user'       => OwenIt\Auditing\Resolvers\UserResolver::class,
-        'ip_address' => OwenIt\Auditing\Resolvers\IpAddressResolver::class,
+        'ip_address' => App\Resolvers\IpAddressResolver::class,
        'user_agent' => OwenIt\Auditing\Resolvers\UserAgentResolver::class,
        'url'        => OwenIt\Auditing\Resolvers\UrlResolver::class,
    ],
];

マスクしたい

監視データは変更前・後の値をそのまま保存しますが、場合によってはマスクして保存したい時もあります。その場合は、監視対象のモデルに設定することで、マスクできます。

app/Item.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use OwenIt\Auditing\Contracts\Auditable;
+use OwenIt\Auditing\Redactors\LeftRedactor;

class Item extends Model implements Auditable
{
    use \OwenIt\Auditing\Auditable;


+    protected $attributeModifiers = [
+        'title' => LeftRedactor::class,
+    ];

LeftRedactorは左から90%マスクし残り10%はそのまま、RightRedactorは右から90%マスクします。マスク部分は#####で保存されます。

特定のイベントのみ監視したい

デフォルトは追加・更新・削除を監視しますが、設定によりイベントを絞り込むことができます。例えば削除のみ監視したい場合は以下のように設定します。

全体

config/audit.php
    'events' => [
-        'created',
-        'updated',
        'deleted',
-        'restored',
    ],

特定の監視対象のみ

app/Item.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use OwenIt\Auditing\Contracts\Auditable;

class Item extends Model implements Auditable
{
    use \OwenIt\Auditing\Auditable;


+    protected $auditEvents = [
+        'deleted',
+    ];

監視ログの上限を設ける

デフォルトでは監視ログは延々と蓄積され続けます。上限を設けたい場合は以下のように設定するこで、上限を超えた古いデータが削除されていきます。

全体

config/audit.php
-    'threshold' => 0, // 0だと上限なし
+    'threshold' => 10,

特定の監視対象のみ

app/Item.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use OwenIt\Auditing\Contracts\Auditable;

class Item extends Model implements Auditable
{
    use \OwenIt\Auditing\Auditable;


+    protected $auditThreshold = 10;
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした