coreproc/nova-auditing-user-fields
A Laravel Nova add-on for Laravel Auditing that adds user fields, so every record shows who created, updated, or deleted it. Displays the responsible user right in your Nova resources for a clear, built-in audit trail.
This release (0.2.0) is primarily a compatibility bump: it targets Laravel 7 and laravel-auditing v10. Treat it as the baseline version for any Laravel 7 app; if you are still on Laravel 6 or auditing v9, stay on the previous package release rather than mixing constraints.
composer require <vendor>/<package>:^0.2 owen-it/laravel-auditing:^10.0
Check composer why owen-it/laravel-auditing afterwards — a stale transitive constraint is the most common cause of a failed upgrade.
php artisan vendor:publish --provider="<Vendor>\<Package>\<PackageServiceProvider>"
php artisan migrate
Look first at:
config/audit.php (driver, console/queue behaviour, audit model)audits migration and tableAuditable trait/contractvendor/owen-it/laravel-auditing changelog for v9 → v10 differencesFirst use case: make one model auditable and read its history back.
use OwenIt\Auditing\Contracts\Auditable as AuditableContract;
use OwenIt\Auditing\Auditable;
class Invoice extends Model implements AuditableContract
{
use Auditable;
}
$invoice->update(['status' => 'paid']);
$latest = $invoice->audits()->latest()->first();
$latest->event; // updated
$latest->getModified(); // ['status' => ['old' => 'draft', 'new' => 'paid']]
Once that works, wire the same retrieval into your admin/detail screen before touching configuration — it validates the migration, trait, and driver in one pass.
Trait + contract on every audited model. The contract is required for type-hinted resolution and for the package to recognise the model as auditable. Add both, not just the trait.
Scope auditing per model. Prefer explicit includes over auditing everything:
protected $auditInclude = ['status', 'total', 'owner_id'];
protected $auditExclude = ['updated_at', 'remember_token'];
Use $auditExclude on noisy columns (timestamps, counters, cached aggregates) to keep the audits table and diff UI readable.
Render history from getModified(). This normalises created/updated/deleted rows and gives you old/new pairs without decoding old_values/new_values yourself. Build one Blade partial or API resource for audit rows and reuse it across models.
$history = $invoice->audits()->with('user')->latest()->paginate(25);
Suppress auditing around bulk or system operations. Imports, seeders, and backfills should not generate thousands of rows:
Invoice::withoutAuditing(function () use ($rows) {
// bulk create/update
});
The same applies to console commands and queue workers where the acting user is not meaningful.
Manual/custom events. For business events that are not CRUD (approval, export, sync), use the package's manual audit entry point on the model and give it a distinct event name. Keep the event names in a small enum/constant class so reporting queries stay consistent.
Custom audit model or driver when needed. Point config/audit.php at your own Audit model if you need extra columns or relationships, and use a custom Auditor implementation if audits must go somewhere other than the database. Both are config-level swaps — no need to fork the package.
Testing. In feature tests, assert on $model->audits after an action rather than mocking the auditor. Use withoutAuditing() in factories/setup so fixtures don't pollute assertions, then re-enable for the specific test.
Upgrade workflow for this release. In a branch: bump both constraints, composer update owen-it/laravel-auditing <vendor>/<package>, republish config only if the package documents new keys, diff the published config against the vendor default, run migrations, then run the audit-related test suite.
composer.lock.config/audit.php, run php artisan config:clear. Stale cached config is the usual reason "my new driver/model isn't being used".audits already exists, vendor:publish + migrate can create a duplicate or conflicting migration. Publish migrations selectively and check the timestamp/name before running.$auditStrict = true, auditing a non-auditable related model throws instead of skipping. Useful in development, risky in production if you enable it late.getModified() returns null for the old side on created. Handle that in diff views rather than assuming both sides exist.old_values/new_values are JSON columns; avoid whereJsonContains assumptions across MySQL versions, and remember that large payloads (long text, base64) bloat the table quickly.auditable_type, auditable_id, and created_at for any table with real traffic; the default migration is intentionally minimal.null, and the write happened inside an audited event (raw query-builder updates bypass Eloquent events entirely).Audit model via config, transformAudit() on the model for redaction/normalisation, custom Auditor driver, and the auditing events — rather than editing vendor files.owen-it/laravel-auditing majors closely, record the Laravel/auditing combination you validated 0.2.0 against in your project README; the next bump will likely be another matrix change.How can I help you explore Laravel packages today?