# Troubleshooting
A compilation of common problems and ways to work around them.
# Recording does not work
You followed all the steps in the documentation and still, Ledger
records are not being created?
# Query Builder vs. Eloquent
Bear in mind that this package relies on Eloquent events (opens new window) and if they don't fire, a Ledger
won't be created.
The most common mistake is performing an update
or delete
operation using a Builder
instance, instead of an Eloquent Model
.
Using the Builder
won't create a Ledger
:
Article::where('id', $id)->update($data);
But using Eloquent
will:
Article::find($id)->update($data);
# Testing and Command Line Interface
By default, Eloquent events fired from a CLI or Testing context, will not be recorded.
Refer to the Recording Contexts section for more details.
# Return value of Altek\Accountant\Resolvers\UserResolver::resolve() must be an instance of Altek\Accountant\Contracts\Identifiable or null
This means the User
model being returned by the resolve()
method doesn't implement the Identifiable
interface.
Refer to the UserResolver documentation for more details.
# Ledgers without modified values are being recorded
A Ledger
is more than just the modified
property value.
There's other metadata like user_*
, recordable_*
, context
, event
, properties
, extra
, url
, ip_address
, user_agent
, signature
and pivot
, which should be more than enough for accountability purposes.
Nevertheless, if such information isn't of use to retain, just register the following observer in the boot()
method of the Ledger
model:
static::creating(function (Ledger $model) {
if (empty($model->modified)) {
return false;
}
});
CAVEAT
Keep in mind that the modified
column of a retrieved
and pivot events (toggled
, synced
, existingPivotUpdated
,attached
and detached
), will always be empty!
# PHP Fatal error: Maximum function nesting level of '512' reached, aborting!
This might happen when a User
model has the retrieved
Eloquent event set as recordable and a retrieval happens.
It boils down to the following:
- A
User
record is retrieved from the database; - Given the
retrieved
event is recordable, the recording process kicks in; - During the data gathering phase for the new
Ledger
, the current user must be resolved for accountability purposes; - The current
User
record is retrieved after being resolved; - The previous step starts the process all over again from step 2, leading to an infinite cycle;
# Solution #1
The simplest way to avoid this, is to disable the retrieved
event from being recordable on a User
model:
<?php
declare(strict_types=1);
namespace App\Models;
use Altek\Accountant\Contracts\Identifiable;
use Altek\Accountant\Contracts\Recordable;
use Illuminate\Database\Eloquent\Model;
class User extends Model implements Identifiable, Recordable
{
use \Altek\Accountant\Recordable;
protected $recordableEvents = [
'created',
'updated',
'restored',
'deleted',
'forceDeleted',
];
/**
* {@inheritdoc}
*/
public function getIdentifier()
{
return $this->getKey();
}
// ...
}
# Solution #2
Another way to work around this, is to implement a UserResolver
where the logic to fetch a User
relies on the Illuminate\Database\Query\Builder
, which doesn't fire events.
# IpAddressResolver incorrectly resolving IP addresses
This usually happens to applications running behind a load balancer (or proxy), in which the IP address of the load balancer/proxy is being returned, instead.
Refer to the IP Address Resolver section for a workaround.
# Unable to encode attribute [properties] for model [Altek\Accountant\Models\Ledger]
This error will happen when creating a Ledger
with one or more binary properties.
In order to solve this, you should use the Base64 cipher.