owen-it / laravel-auditing

Record the change log from models in Laravel
https://laravel-auditing.com
MIT License
3.05k stars 390 forks source link

Auditing for each relationship being saved more than once in multiple relationship auditing with auditSync #942

Closed tiagocpeixoto closed 5 months ago

tiagocpeixoto commented 5 months ago

PHP Version

8.2

Laravel Version

11.x

Package Version

13.6.5

Description

When I use auditSync with more than one relation in the same db transaction, the audit for each relation is being saved more than once.

Here is my code (in the same db transaction):

// the model being saved
$result = $model->save();

if (isset($validated['assignee_ids'])) {
    $model->auditSync('assignees', $validated['assignee_ids']);
}

if (isset($validated['customer_ids'])) {
    $model->auditSync('customers', $validated['customer_ids']);
}

if (isset($validated['legal_matter_ids'])) {
    $model->auditSync('legalMatters', $validated['legal_matter_ids']);
}

The result is: three relationship audit records are saved in the database (ignoring the model audit here, which is irrelevant for the present case), some of them duplicating other relationship audits.

- First audit record ('new_values' column):

{
  "assignees": [
    {
      "id": 6,
      ...
    }
  ]
}

- Second audit record ('new_values' column)

{
  "assignees": [
    {
      "id": 6,
    }
  ],
  "customers": [
    {
      "id": 2,
      ...
    }
  ]
}

- Third audit record ('new_values' column):

{
  "assignees": [
    {
      "id": 6,
      ...
    }
  ],
  "customers": [
    {
      "id": 2,
      ...
    }
  ],
  "legalMatters": [
    {
      "id": 3,
      ...
    }
  ]
}

Is there a problem with my code or it may be a bug?

Thanks in advance.

Steps To Reproduce

Execute a code that audits more than one relation, as shown in the example below:

// the model being saved
$result = $model->save();

if (isset($validated['assignee_ids'])) {
    $model->auditSync('assignees', $validated['assignee_ids']);
}

if (isset($validated['customer_ids'])) {
    $model->auditSync('customers', $validated['customer_ids']);
}

if (isset($validated['legal_matter_ids'])) {
    $model->auditSync('legalMatters', $validated['legal_matter_ids']);
}

Possible Solutions

Audit all the relations in just one audit record OR one audit record per synced relation.