承接 rasuvaeff/yii3-audit-log 相关项目开发

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

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

rasuvaeff/yii3-audit-log

Composer 安装命令:

composer require rasuvaeff/yii3-audit-log

包简介

Audit trail for Yii3 applications: who changed what and when, with sensitive value masking

README 文档

README

Stable Version Total Downloads Build Static analysis Psalm Level PHP License

Audit trail for Yii3 applications: who changed what and when, with sensitive value masking. Stateless core — bring your own writer (DB adapter lives in a separate package).

Using an AI coding assistant? llms.txt has a compact API reference you can use.

Requirements

  • PHP 8.3+
  • psr/clock ^1.0

Installation

composer require rasuvaeff/yii3-audit-log

Yii3 config-plugin

The package ships config/di.php and config/params.php via config-plugin. It wires AuditLogger and SensitiveValueMasker, but intentionally does not bind AuditWriter or Psr\Clock\ClockInterface. Install exactly one writer adapter or bind AuditWriter in your application config:

use Psr\Clock\ClockInterface;
use Rasuvaeff\Yii3AuditLog\AuditWriter;

return [
    AuditWriter::class => MyAuditWriter::class,
    ClockInterface::class => MyClock::class,
];

Default params:

return [
    'rasuvaeff/yii3-audit-log' => [
        'sensitiveKeys' => ['password', 'secret', 'token', 'api_key', 'credit_card'],
        'skipEmptyChangeSets' => true,
    ],
];

Usage

Basic logging

use Rasuvaeff\Yii3AuditLog\AuditActor;
use Rasuvaeff\Yii3AuditLog\AuditChangeSet;
use Rasuvaeff\Yii3AuditLog\AuditLogger;
use Rasuvaeff\Yii3AuditLog\AuditSubject;
use Rasuvaeff\Yii3AuditLog\InMemoryAuditWriter;

$logger = new AuditLogger(writer: $writer, clock: $clock);

$logger->logChange(
    actor: AuditActor::user(id: $userId, name: 'John'),
    subject: AuditSubject::of(type: 'order', id: (string) $orderId),
    changes: AuditChangeSet::fromArrays(
        old: ['status' => 'new', 'total' => 0],
        new: ['status' => 'paid', 'total' => 99.95],
    ),
);

Implementing a writer

use Rasuvaeff\Yii3AuditLog\AuditEvent;
use Rasuvaeff\Yii3AuditLog\AuditWriter;

final readonly class DbAuditWriter implements AuditWriter
{
    public function write(AuditEvent $event): void
    {
        // INSERT INTO audit_log ...
        // $event->getId(), $event->getActor(), $event->getAction(),
        // $event->getSubject(), $event->getChangeSet(), $event->getOccurredAt()
    }
}

Sensitive value masking

use Rasuvaeff\Yii3AuditLog\AuditLogger;
use Rasuvaeff\Yii3AuditLog\SensitiveValueMasker;

$logger = new AuditLogger(
    writer: $writer,
    clock: $clock,
    masker: new SensitiveValueMasker(), // masks password, secret, token, api_key, credit_card
);

// Custom sensitive keys:
$masker = new SensitiveValueMasker(sensitiveKeys: ['ssn', 'pin', 'password']);

System actor

$logger->logCreate(
    actor: AuditActor::system(),
    subject: AuditSubject::of(type: 'config', id: 'smtp'),
    changes: AuditChangeSet::fromArrays(old: [], new: ['host' => 'mail.example.com']),
);

Request metadata

use Rasuvaeff\Yii3AuditLog\AuditMetadata;

$logger->logChange(
    actor: $actor,
    subject: $subject,
    changes: $changes,
    metadata: new AuditMetadata(
        requestId: $request->getHeaderLine('X-Request-Id'),
        ip: $request->getServerParams()['REMOTE_ADDR'] ?? null,
        userAgent: $request->getHeaderLine('User-Agent'),
    ),
);

API reference

AuditLogger

Method Description
__construct(writer, clock, masker?, skipEmptyChangeSets?) Default: skip empty sets = true
log(actor, action, subject, changes, metadata?) Generic log
logCreate(actor, subject, changes, metadata?) action = 'create'
logChange(actor, subject, changes, metadata?) action = 'update'
logDelete(actor, subject, changes, metadata?) action = 'delete'

AuditActor

Method Description
::user(id, name?) User actor
::system() System actor (id = null)
getType() 'user', 'system', or custom
getId() ?string
getName() ?string
isSystem() bool

AuditSubject

Method Description
::of(type, id) Factory
getType() Resource type
getId() Resource ID

AuditChangeSet

Method Description
::fromArrays(old, new) Computes diff; only changed fields included
::empty() Empty change set
getChanges() list<AuditChange>
isEmpty() bool
count() Number of changes

AuditChange

Method Description
getField() Field name
getOldValue() mixed
getNewValue() mixed

SensitiveValueMasker

Method Description
__construct(sensitiveKeys?) Default: password, secret, token, api_key, credit_card
mask(array) Returns array with sensitive values replaced by ***
maskChangeSet(AuditChangeSet) Returns new AuditChangeSet with masked values

Security

  • Masker is applied inside AuditLogger before the event reaches the writer — secrets never reach storage.
  • Masking is case-insensitive: Password, PASSWORD, password all masked.
  • DB writer implementations must use parameterized queries.

Examples

See examples/ for complete usage examples.

Development

make install
make build
make cs-fix
make test
make test-coverage
make mutation
make release-check

make test-coverage and make mutation bootstrap pcov inside the composer:2 container because the base image has no coverage driver.

License

BSD-3-Clause. See LICENSE.md.

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: BSD-3-Clause
  • 更新时间: 2026-06-20

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固