Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Model Auditlog Laravel Package

always-open/laravel-model-auditlog

Laravel Model AuditLog automatically tracks changes to your Eloquent models, recording creates, updates, and deletes with the data needed for a clear audit trail. Add lightweight, configurable history to models without cluttering your app logic.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the package with Composer:

    composer require always-open/laravel-model-auditlog
    
  2. Publish the config and migration files:

    php artisan vendor:publish --provider="AlwaysOpen\ModelAuditLog\AuditLogServiceProvider"
    

    Check the published config/auditlog.php first — this is where you configure the audit model, user resolver, and attribute filtering.

  3. Run the migrations to create the audit log table:

    php artisan migrate
    
  4. Add the package’s auditable trait to any Eloquent model you want to track:

    use AlwaysOpen\ModelAuditLog\Traits\Auditable;
    
    class Post extends Model
    {
        use Auditable;
    }
    
  5. First use case: create or update a record and inspect its audit history:

    $post = Post::create(['title' => 'Hello']);
    $post->update(['title' => 'Hello, world']);
    
    $post->audits; // collection of audit entries
    

    Confirm that old_values, new_values, event, user_id, and timestamps are populated as expected.

Upgrading from v9: v10.0.0 is primarily a Laravel 13 compatibility release. Before upgrading, verify your PHP version meets Laravel 13’s requirements, run the full test suite, and review the package’s upgrade guide for any trait or config signature changes. If you are not yet on Laravel 13, stay on the latest v9.x release.

Implementation Patterns

Trait-based auditing for standard Eloquent models

Apply the Auditable trait to models that need automatic create/update/delete tracking. This is the lowest-effort path and covers the majority of day-to-day use cases.

class Invoice extends Model
{
    use Auditable;
}

Custom audit models and relationships

If you need extra fields, custom casts, or a different table, extend or configure the package’s audit model in config/auditlog.php. Keep a dedicated AuditLog model so you can add scopes, accessors, and relationships without touching vendor code.

// config/auditlog.php
'model' => App\Models\AuditLog::class,

Attribute filtering and redaction

Use the config file or model-level overrides to exclude noisy or sensitive attributes. Typical exclusions include updated_at, password hashes, API tokens, and large JSON blobs.

protected $auditExclude = [
    'password',
    'remember_token',
    'updated_at',
];

This is important for both security and table size.

User attribution

Configure the resolver that identifies the acting user. In queued jobs, console commands, and tests there is often no authenticated user, so make the resolver nullable and provide a fallback such as a system user ID or null.

'user' => [
    'resolver' => function () {
        return auth()->id();
    },
],

Manual auditing for non-Eloquent events

For actions that do not map cleanly to model events — imports, bulk operations, external API syncs — use the package’s manual audit API if available, or dispatch an audit entry directly through the audit model. Wrap bulk writes in a transaction and create one audit entry per affected record where traceability matters.

Integration with Laravel events and queues

Audit logging is synchronous by default because it hooks into Eloquent events. If audit writes become a performance bottleneck, consider listening to the package’s audit-created event and offloading downstream processing (notifications, search indexing) to a queue rather than moving the audit write itself.

Testing

Use database transactions or RefreshDatabase in tests. Assert on audit entries directly:

$this->assertDatabaseHas('audit_logs', [
    'auditable_type' => Post::class,
    'auditable_id' => $post->id,
    'event' => 'updated',
]);

For models with sensitive attributes, add a regression test that asserts excluded fields never appear in old_values or new_values.

Gotchas and Tips

Major version upgrade discipline

v10.0.0 is a major release. Even though the release note only calls out Laravel 13 support, major bumps can include dropped PHP versions, changed trait namespaces, or config key renames. Read the full changelog between v9.5.0 and v10.0.0, run composer why-not if the upgrade is blocked, and test on a staging branch before production.

Laravel 13 compatibility ripple effects

If you upgrade to Laravel 13, check your other packages first. An audit log package is rarely the only dependency that needs a framework major. Use composer update --with-all-dependencies cautiously and review the lock file diff.

No authenticated user in background contexts

Queued jobs, scheduled commands, and tests will often resolve auth()->id() to null. Decide whether that is acceptable or whether you need a system actor. Do not assume every audit row has a user.

Sensitive data leakage

Audit logs are often retained far longer than the source records and may be exported to data warehouses. Exclude passwords, tokens, PII, and encrypted fields explicitly. Do not rely on model $hidden — that affects serialization, not audit capture.

Soft deletes and force deletes

Auditing deleted, restored, and forceDeleted events requires the model to use SoftDeletes and the package to be configured to capture those events. Verify the behavior in tests; a hard delete can otherwise leave you with an audit trail that is harder to interpret.

Transaction boundaries

Audit entries are written inside the same database transaction as the model change in most configurations. If the transaction rolls back, the audit entry disappears too. That is usually correct, but it means audit logs are not a substitute for external, append-only compliance storage.

Large attribute payloads

Storing full old_values and new_values JSON for wide models or large text columns can bloat the audit table quickly. Exclude large fields, store only changed attributes if the package supports it, and add indexes on auditable_type, auditable_id, and created_at.

Polymorphic relation integrity

Audit rows reference models polymorphically. If a model is deleted or its class is renamed, historical audit rows can become orphaned or unreadable. Avoid renaming audited model classes without a migration strategy, and consider storing a stable morph alias.

Config caching

After changing config/auditlog.php in production, run php artisan config:cache. A stale config cache is a common reason why exclusions or user resolvers appear to be ignored.

Extension points

Prefer extending the audit model and overriding config values over modifying vendor files. If you need custom behavior on every audit write, look for the package’s events or a publishable audit model before reaching for a fork.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib