0

I'm implementing a LOG of the events that occurs on the system. In other words, detect when an object is created, and save the data that was created. When an update comes, I need to store the previous object state and the new one. As I'm using API resources with custom data implementations, I'm reusing them to gather all the needed information.

public function update(Request $request, Attendant $attendant)
{
    $attendantData = $request->input('attendant');

    $prevResource = new AttendantResource($attendant);
    $attendant = AttendantService::Update($attendant, $attendantData);

    $resource = new AttendantResource($attendant);

    $this->createLog($prevResource, $resource);

    return $resource;
}

In the previous code, create a new resource before the Attendant is modified. But at the end, $prevResource and $resource have the same data. The information from $prevResource is update toO.

Is there a way to clone the Model? or instead, Is there a way to prevent the reference update from the $prevResource?

Jacobo
  • 1,259
  • 2
  • 19
  • 43

2 Answers2

0

Use laravel's model observers(https://laravel.com/docs/5.8/eloquent#observers) to observe events on models and log what you need to. You can observe created, creating, updated, updating, deleted, deleting, saved, saving events.

kkyeboah
  • 186
  • 4
  • That is an amazing approach. Do you know if I can get the previous object values before the update? https://stackoverflow.com/questions/17367383/get-previous-attribute-value-in-eloquent-model-event I read that answer, but I don’t know if that function return the first ever created data or the previous data before the last update. – Jacobo Apr 01 '19 at 23:44
  • When using the `creating` or `updating` observer, you can get the model attribute's previous value with `$model->getOriginal('attribute')`. – kkyeboah Apr 02 '19 at 00:20
  • This helped me a lot. – Jacobo Apr 02 '19 at 00:59
0

In my opinion this is not the way to handle this type of problem (in the controller).

What you actually want to do is Register an event listener that does the logging when your eloquent model is updated. There are also model "observers".

There is a library that already handles the specifics of how to make all of this work together that at very least can act as an example of how to set everything up, but is already capable of doing what you want.

Here is the specific documentation on "Logging Model Events."

The nice thing about using the Spatie Logger is that it's been manifested as a simple trait you add to your model. Here's some example code from the documentation:

use Illuminate\Database\Eloquent\Model;
use Spatie\Activitylog\Traits\LogsActivity;

class NewsItem extends Model
{
    use LogsActivity;   
    protected static $logAttributes = ['*'];       
    protected static $logAttributesToIgnore = ['text'];       
    protected static $logOnlyDirty = true;
}

This illustrates a few different customizations including the use of $logOnlyDirty that will only log changed items, vs the default of providing a complete before/after of the entity. You can also ignore certain attributes you don't care about (timestamps or calculated fields for example.

gview
  • 14,876
  • 3
  • 46
  • 51
  • Yes, but my main problem is that I still need the previous values even with the model relationships alongside the new values. This because they need to be able to compare the previous data and the new one at the same time in the case of an update – Jacobo Apr 01 '19 at 23:59
  • The logging includes a before/after view of the data. That is intrinsic to the general idea of this event handling. You can think of these as Eloquent's version of database triggers if you know what those are. – gview Apr 02 '19 at 00:05