The metadata and modified data can be accessed in several ways.
The Audit data is referred as metadata, since it's information about the modified attributes of an Auditable model.
Metadata can be fetched through the getMetadata() method as an array.
var_dump($audit->getMetadata());Output:
array(11) {
["audit_id"]=>
string(1) "1"
["audit_event"]=>
string(7) "updated"
["audit_url"]=>
string(29) "http://example.com/articles/1"
["audit_ip_address"]=>
string(9) "127.0.0.1"
["audit_user_agent"]=>
string(68) "Mozilla/5.0 (X11; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0"
["audit_tags"]=>
string(7) "foo,bar"
["audit_created_at"]=>
string(19) "2017-01-01 01:02:03"
["audit_updated_at"]=>
string(19) "2017-01-01 01:02:03"
["user_id"]=>
string(1) "1"
["user_type"]=>
string(8) "App\User"
["user_email"]=>
string(15) "bob@example.com"
["user_name"]=>
string(3) "Bob"
}Passing true as the first argument will convert the data into its JSON representation.
echo $audit->getMetadata(true, JSON_PRETTY_PRINT);{tip} The second argument accepts a bitmask of options. To know more, read the
json_encode()function documentation.
Output:
{
"audit_id": "1",
"audit_event": "updated",
"audit_url": "http:\/\/example.com\/articles\/1",
"audit_ip_address": "127.0.0.1",
"audit_user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0",
"audit_tags": "foo,bar",
"audit_created_at": "2017-01-01 01:02:03",
"audit_updated_at": "2017-01-01 01:02:03",
"user_id": "1",
"user_type": "App\\User",
"user_email":"bob@example.com",
"user_name":"Bob"
}{note} Depending on the
$visibleproperty of theUsermodel, otheruser_prefixed attributes may become available.
Lastly, the Audit attributes can also be accessed directly, like in any other Eloquent model:
echo $audit->id.PHP_EOL;
echo $audit->event.PHP_EOL;
echo $audit->url.PHP_EOL;
echo $audit->ip_address.PHP_EOL;
echo $audit->user_agent.PHP_EOL;
echo $audit->tags.PHP_EOL;
echo implode(',', $audit->getTags()).PHP_EOL;
echo $audit->created_at->toDateTimeString().PHP_EOL;
echo $audit->updated_at->toDateTimeString().PHP_EOL;
echo $audit->user_id.PHP_EOL;
echo $audit->user_type.PHP_EOL;
echo $audit->user->email.PHP_EOL;
echo $audit->user->name.PHP_EOL;Output:
1
updated
http://example.com/articles/1
127.0.0.1
Mozilla/5.0 (X11; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
foo,bar
foo,bar
2017-01-01 01:02:03
2017-01-01 01:02:03
1
App\User
bob@example.com
BobThe modified data is a set of Auditable model attributes that changed since the last event: created, updated, deleted and restored.
Only modified attributes will make part of the array, which consists in the old and new values for each one.
var_dump($audit->getModified());Output:
array(2) {
["title"]=>
array(2) {
["new"]=>
string(28) "How To Audit Eloquent Models"
["old"]=>
string(19) "How to audit models"
}
["content"]=>
array(2) {
["new"]=>
string(56) "First, start by installing the laravel-auditing package."
["old"]=>
string(16) "This is a draft."
}
}Like with the getMetadata() method, passing true as the first argument will convert the data into a JSON string.
echo $audit->getModified(true);Output:
{"title":{"new":"How To Audit Eloquent Models","old":"How to audit models"},"content":{"new":"First, start by installing the laravel-auditing package.","old":"This is a draft."}}{tip} The
getModified()method honors all attribute mutators and/or casts defined in theAuditablemodel, transforming the data accordingly.
Direct access to the old and new values is also possible:
var_dump($audit->old_values, $audit->new_values);Output:
array(2) {
["title"]=>
string(19) "How to audit models"
["content"]=>
string(16) "This is a draft."
}
array(2) {
["title"]=>
string(28) "How To Audit Eloquent Models"
["content"]=>
string(56) "First, start by installing the laravel-auditing package."
}To better understand how the Audit methods can be used, here are some presentation examples.
Displaying a Collection of Audit models in an HTML unordered list.
Article translation file:
return [
// ...
'unavailable_audits' => 'No Article Audits available',
'updated' => [
'metadata' => 'On :audit_created_at, :user_name [:audit_ip_address] updated this record via :audit_url',
'modified' => [
'title' => 'The Title has been modified from <strong>:old</strong> to <strong>:new</strong>',
'content' => 'The Content has been modified from <strong>:old</strong> to <strong>:new</strong>',
],
],
// ...
];Blade template:
<ul>
@forelse ($audits as $audit)
<li>
@lang('article.updated.metadata', $audit->getMetadata())
@foreach ($audit->getModified() as $attribute => $modified)
<ul>
<li>@lang('article.'.$audit->event.'.modified.'.$attribute, $modified)</li>
</ul>
@endforeach
</li>
@empty
<p>@lang('article.unavailable_audits')</p>
@endforelse
</ul>{tip} The use of pagination should be taken into account when dealing with large
Auditcollections.
Present a single Audit using a diff like view.
Common translation file:
return [
// ...
'attribute' => 'Attribute',
'event' => 'Event',
'id' => 'ID',
'ip_address' => 'IP Address',
'user_agent' => 'User Agent',
'new' => 'New',
'old' => 'Old',
'url' => 'URL',
'user' => 'User',
'tags' => 'Tags',
// ...
];Vue app to set the data:
new Vue({
el: '.container',
data: {
metadata: JSON.parse(document.getElementById('article').getAttribute('data-metadata')),
modified: JSON.parse(document.getElementById('article').getAttribute('data-modified'))
}
});Blade template with Vue data bindings:
<div id="article" class="container" data-metadata='{!! $audit->getMetadata(true) !!}' data-modified='{!! $audit->getModified(true) !!}'>
<div v-model="metadata">
<div class="row">
<div class="col-md-3">
<strong>@lang('common.id')</strong>
</div>
<div class="col-md-9">@{{ metadata.audit_id }}</div>
</div>
<div class="row">
<div class="col-md-3">
<strong>@lang('common.event')</strong>
</div>
<div class="col-md-9">@{{ metadata.audit_event }}</div>
</div>
<div class="row">
<div class="col-md-3">
<strong>@lang('common.user')</strong>
</div>
<div class="col-md-9">@{{ metadata.user_name }}</div>
</div>
<div class="row">
<div class="col-md-3">
<strong>@lang('common.ip_address')</strong>
</div>
<div class="col-md-9">@{{ metadata.audit_ip_address }}</div>
</div>
<div class="row">
<div class="col-md-3">
<strong>@lang('common.user_agent')</strong>
</div>
<div class="col-md-9">@{{ metadata.audit_user_agent }}</div>
</div>
<div class="row">
<div class="col-md-3">
<strong>@lang('common.tags')</strong>
</div>
<div class="col-md-9">@{{ metadata.audit_tags.join() }}</div>
</div>
<div class="row">
<div class="col-md-3">
<strong>@lang('common.url')</strong>
</div>
<div class="col-md-9">@{{ metadata.audit_url }}</div>
</div>
</div>
<hr/>
<table class="table table-striped">
<thead>
<tr>
<th>@lang('common.attribute')</th>
<th>@lang('common.old')</th>
<th>@lang('common.new')</th>
</tr>
</thead>
<tbody>
<tr v-for="(value, attribute) in modified">
<td><strong>@{{ attribute }}</strong></td>
<td class="danger">@{{ value.old }}</td>
<td class="success">@{{ value.new }}</td>
</tr>
</tbody>
</table>
</div>