承接 mxnwire/laravel-audit-log 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

mxnwire/laravel-audit-log

Composer 安装命令:

composer require mxnwire/laravel-audit-log

包简介

Activity log viewer layered on top of spatie/laravel-activitylog

README 文档

README

Activity log viewer and logger layered on top of spatie/laravel-activitylog.

Spatie owns the storage (activity_log table, polymorphic causer/subject, and the activitylog:clean prune command). This package adds:

  • A activity_log() helper and ActivityLogService that freeze actor identity and request context at write time.
  • A built-in viewer UI (filterable table, no JS build step required) protected by a permission gate.
  • ActivityMetadata / Change value objects for structured before/after diffs in the properties column.

Requirements

Dependency Version
PHP ^8.1
Laravel 10 or 11
spatie/laravel-activitylog ^4.0

Installation

1. Install the package via Composer:

composer require mxnwire/laravel-audit-log

The service provider is auto-discovered — no manual registration needed.

2. Install and run spatie's migration:

If you have not already done so for spatie/laravel-activitylog:

php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag="activitylog-migrations"
php artisan migrate

3. Publish the package assets (optional but recommended):

php artisan vendor:publish --tag="audit-log"

This copies two things:

Source Destination
config/audit-log.php config/audit-log.php
resources/views/ resources/views/vendor/audit-log/

You only need to publish if you want to customise views or the config file. The package works out of the box without publishing.

Configuration

After publishing, edit config/audit-log.php:

return [

    // The ability string checked by the route middleware `can:X`.
    // Must be a permission defined in your host app (e.g. via spatie/laravel-permission).
    // Can also be set via the AUDIT_LOG_GATE environment variable.
    'gate' => env('AUDIT_LOG_GATE', 'ACTIVITY_LOGS_ALL'),

    // A callable that resolves the actor's role label from a User model instance.
    // null = falls back to $user->role ?? $user->urole ?? null.
    'role_resolver' => null,

    // URL prefix for the viewer routes.
    // Changing this also renames the named routes `audit-log.index` and `audit-log.data`.
    'route_prefix' => 'mxn/audit-logs',

    // Eloquent model used to populate the "User" filter dropdown.
    // The model must have `id` and `name` columns.
    // Set to null to hide the user filter entirely.
    'user_model' => 'App\\Models\\User',

    // Blade layout the viewer page extends.
    // Override to wrap the viewer inside your own app shell.
    // The layout must @yield('content') and @yield('script').
    'layout' => 'audit-log::layouts.app',

];

Environment variable

Variable Default Description
AUDIT_LOG_GATE ACTIVITY_LOGS_ALL Permission gate for the viewer routes

Usage

Logging an activity

Use the global helper (available automatically — no import needed):

activity_log('user.login');

Or inject the service directly:

use Mxnwire\AuditLog\Services\ActivityLogService;

class AuthController extends Controller
{
    public function __construct(private ActivityLogService $auditLog) {}

    public function login(Request $request)
    {
        // ... authenticate ...
        $this->auditLog->log('user.login');
    }
}

Signature

activity_log(
    string $action,                      // dotted verb, e.g. 'broadsheet.viewed'
    ?Model $subject = null,              // the record acted on
    ?ActivityMetadata $metadata = null,  // structured diff / extra fields
    ?string $description = null          // optional human-readable label
): void

The dotted action maps to spatie's two indexable columns:

'broadsheet.updated'  →  log_name = 'broadsheet'
                         event    = 'updated'

'login'               →  log_name = 'login'
                         event    = null

The __actor and __request context is always merged into spatie's properties JSON column automatically:

{
  "__actor":   { "name": "Jane Smith", "role": "admin" },
  "__request": { "method": "POST", "route": "posts.store", "url": "...", "ip": "...", "user_agent": "..." }
}

Adding structured metadata

Use ActivityMetadata to attach typed field-level detail to a log entry.

Arbitrary fields:

use Mxnwire\AuditLog\Activity\Metadata\ActivityMetadata;

activity_log(
    'user.login',
    subject: $user,
    metadata: ActivityMetadata::make(['via' => 'password'])
);

Before/after diff for a specific field:

use Mxnwire\AuditLog\Activity\Metadata\ActivityMetadata;
use Mxnwire\AuditLog\Activity\Metadata\Change;

activity_log(
    'subscription.updated',
    subject: $subscription,
    metadata: ActivityMetadata::make([
        'level' => Change::make($old->level, $new->level),
    ])
);

Stored in properties as:

{ "level": { "old": 2, "new": 5 } }

Auto-diff two arrays (keeps only changed keys):

$metadata = ActivityMetadata::diff(
    $record->getOriginal(),  // before
    $record->getAttributes() // after
);

activity_log('post.updated', subject: $record, metadata: $metadata);

You can restrict which keys are diffed with the optional third argument:

ActivityMetadata::diff($before, $after, keys: ['title', 'status', 'published_at']);

Fluent chaining:

ActivityMetadata::diff($before, $after)
    ->with('trigger', 'bulk-import')
    ->with('row_count', 500);

Viewing logs

The package registers two routes automatically:

Route Named route Description
GET /mxn/audit-logs audit-log.index Viewer page
GET /mxn/audit-logs/data audit-log.data JSON data endpoint for the table

Both routes are protected by auth and can:{gate} middleware. The gate defaults to ACTIVITY_LOGS_ALL; change it via AUDIT_LOG_GATE in your .env or in the published config.

Customisation

Custom viewer layout

To embed the viewer inside your own app shell, set layout in the config to any Blade layout that yields content and script:

'layout' => 'layouts.app',

Your layout must contain:

@yield('content')
@yield('script')

Custom route prefix

'route_prefix' => 'admin/audit-logs',

The named routes (audit-log.index, audit-log.data) follow the prefix automatically.

Custom role resolver

If your app does not use a role or urole attribute directly on the User model:

'role_resolver' => fn ($user) => $user->roles->first()?->name,

Custom activity type registry

The package resolves filter options (log names, events, subject types) from the activity_log table at runtime via ActivityTypeRegistry. To provide a static list instead — or to customise the queries — bind your own implementation in a service provider:

use Mxnwire\AuditLog\Contracts\ActivityTypeRegistryContract;

$this->app->bind(ActivityTypeRegistryContract::class, MyCustomRegistry::class);

Your class must implement logNames(): array, events(): array, and subjectTypes(): array.

Development

Running the tests

The test suite uses Orchestra Testbench and an in-memory SQLite database — no external database or running Laravel app is required.

1. Install dev dependencies (first time only):

composer install

2. Run the full suite:

composer test

Or call PHPUnit directly:

./vendor/bin/phpunit

3. Run a single suite:

./vendor/bin/phpunit --testsuite Unit
./vendor/bin/phpunit --testsuite Feature

4. Run a single test file:

./vendor/bin/phpunit tests/Unit/ActivityMetadataTest.php
./vendor/bin/phpunit tests/Unit/ChangeTest.php
./vendor/bin/phpunit tests/Feature/ActivityLogServiceTest.php

5. Run a single test by name:

./vendor/bin/phpunit --filter "test_name_here"

Test structure

Path What it covers
tests/Unit/ActivityMetadataTest.php ActivityMetadata value object — make, diff, with
tests/Unit/ChangeTest.php Change value object — serialisation
tests/Feature/ActivityLogServiceTest.php ActivityLogService end-to-end against a real SQLite DB
tests/TestCase.php Base case — boots Testbench, runs spatie migrations in-memory

License

MIT

统计信息

  • 总下载量: 1
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 8
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-13

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固