After you require the package. When you do php artisan migrate you will notice a new migration/table getting migrated.
It is the create_access_logs_table migration.
That is because the AccessLogMiddleware saves logged api endpoints in this table.
To use the AccessLogMiddleware, all you have to do is wrap the middleware access.log around your desired endpoints like below
// api.php
Route::middleware(['access.log'])->group(function () {
Route::get('/hello', function () {
return 'Hello World';
});
});
After you wrapped the access.log middleware around your api endpoints.
Now, if you hit that endpoint yourUrl:8000/hello it will return the string Hello World.
If you go to your access log table now you will see that the endpoint information were saved to the access log database table.

It has information like:
Request bodies are recorded, so credentials must not be. Anything matching the exclusion list is dropped from both the stored body and the query string before the row is written:
password, password_confirmation, current_password,
new_password, new_password_confirmation,
remember_token, api_token, access_token, refresh_token,
api_key, client_secret, secret, token
current_password matters in particular: it is the field Laravel Breeze's password-update form submits, so without it a password-change route logged the user's existing password in plaintext.
A login request therefore records who tried to sign in without recording what they typed:
{"email": "user@example.com"}
Matching is case-insensitive and applies at any depth, so a nested user[password] is redacted by the bare password entry:
{"user": {"email": "user@example.com"}}
An entry written in dot notation targets one specific nested key instead, leaving a same-named key elsewhere alone:
'excluded_attributes' => ['user.pin'],
The list is shared with the audit trail by default. Override it independently when the access log needs different rules:
'access_log' => [
'excluded_attributes' => ['password', 'pin', 'otp'],
],
Setting it to null falls back to lara-util-x.audit.excluded_attributes.
Changed in v1.5.5.
current_password,new_password,api_key, andclient_secretwere added to the defaults, redaction now reaches nested keys instead of only top-level ones, and query-string parameter names are matched case-insensitively.Changed in v1.5.4. Earlier releases stored
json_encode($request->all())verbatim, so placing the middleware on a login route wrote plaintext passwords intoaccess_logs, andfullUrl()persisted any token passed as a query parameter. If you have been running this middleware on authentication routes, treat the existing rows as compromised credentials and purge them.
Access logs accumulate on every request. AccessLog is prunable, but php artisan model:prune on its own will never find it: without --model the command only scans app/Models, so a model living in vendor/ is never discovered.
Name the model explicitly:
use Illuminate\Support\Facades\Schedule;
Schedule::command('model:prune', [
'--model' => [\LaraUtilX\Models\AccessLog::class],
])->daily();
--model limits that run to the models you list. Keep this schedule separate from any model:prune you already run for your own models, rather than merging them into one command, or one of the two sets will stop being pruned.
Retention is configurable, and null keeps rows indefinitely:
'access_log' => [
'retention_days' => 30,
],
Added in v1.5.4. The table previously grew without bound.
You can publish the package's migrations if you want to customise the table:
The AccessLog model is not publishable. A published copy kept its LaraUtilX namespace while landing in app/Models, so Composer never autoloaded it and every call still resolved to the package's class. Extend it instead:
namespace App\Models;
class AccessLog extends \LaraUtilX\Models\AccessLog
{
//
}
You can publish the package's migrations through this command:
php artisan vendor:publish --tag=lara-util-x-migrations