Trochę ostatnio się bawiłem z monitorowaniem zmian dokonywanych przez użytkowników. Głównym wyzwaniem było przedstawienie logów dla innych administratorów w sposób zrozumiały i czytelny i w języku polskim.

Paczka laravel-activitylog

Instalacja laravel-activitylog jest prosta. Wystarczy postępować zgodnie z instrukcją na stronie repozytorium, czyli.
composer require spatie/laravel-activitylog
Następnie
php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag="migrations"

I tutaj jeśli z jakiś względów wasza baza danych nie obsługuję typu danych JSON, należy przejść do pliku z migracją czyli, create_activity_log_table i zamienić

$table->json('properties')->nullable();

na

$table->text('properties')->nullable();

Następnie migracja
php artisan migrate
W modelach, które chcemy monitorować pod względem zmian dodajemy

protected static $logAttributes = [TU NASZE ATRYBUTY,KTÓRE CHCEMY ZAPISYWAĆ]

Możemy oczywiście zrobić, w szybszy i mniej bezpieczny sposób, wrzucając wszystko jak leci:

protected static $logAttributes = [*]

oraz nazwę loga i $logOnlyDirty = true, czyli zapisujemy, tylko te atrybuty, które zostały rzeczywiście zmienione.

protected static $logName = 'Przyjazna nazwa loga np. specyfikacja klienta';
protected static $logOnlyDirty = true;

Do kolejnych modeli, które chcemy monitorować, wykonujemy tą samą operację.

Wyświetlamy poprzez wywołanie

Activity::all()

i tutaj, zaczyna się to, co należało naprawić, czyli formatowanie logów, które będą zrozumiałe dla innych administratorów.
Do formatowania stworzymy nowy model php artisan make:model Activity

Model Activity.php

Do formatowania najlepiej było użyć mutatorów.

namespace App;

use Illuminate\Database\Eloquent\Model;

class Activity extends Model
{
    protected $table = 'activity_log';

    /**
     * Użyto mutatora dla Properties, aby edytowane lub nowo utworzone atrybuty, które są przechowywane jako JSON,
     * byłby przedstawione w sposób:
     * Zmianiono atrybut x z *stara wartość* na *nową wartość*
     * @param $value
     * @return string
     */
    public function getPropertiesAttribute($value)
    {
        $array = json_decode($value, true);
        if(isset($array["old"])) {
            $allKeys = array_keys($array["old"]);
            for($i = 0; $i<sizeof($array["old"]);$i++) {
                $result[] = [
                    'key'=>$allKeys[$i],
                    'old'=> array_values($array["old"])[$i],
                    'new'=> array_values($array["attributes"])[$i]
                ];
            }
            return $result;
        } else if(isset($array["attributes"]))  {
            $allKeys = array_keys($array["attributes"]);
            for($i = 0; $i<sizeof($array["attributes"]);$i++) {
                $result[] = [
                    'key'=>$allKeys[$i],
                    'new'=> array_values($array["attributes"])[$i]
                ];
            }
            return $result;
        }
        return null;
    }

    /**
     * Użyto mutatora, aby przetłumaczyć nazwę operacji, której dokonał użytkownik.
     * @param $eventName
     * @return string
     */
    public function getDescriptionAttribute($eventName) {
        if ($eventName == 'created') {
            return 'Uwtorzył(a) rekord w bazie';
        }else if ($eventName == 'updated') {
            return 'Zaktualizował(a) rekord w bazie';
        }else if ($eventName == 'deleted') {
            return 'Usunął/eła rekord w bazie';
        }
        return '';
    }

    /**
     * Relacja, z użytkownikiem, który dokonał zmian
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function causer() {
        return $this->belongsTo('App\User');
    }
}

I właściwie gotowe. Wystarczy, że wywołamy w view {{$activit->description}} czy {!!$activit->properties!!}
Przykład

<ul>
    @if($activity)
        @foreach($activity as $singleActivity)
             <li class="left clearfix">
                 <span class="img pull-left">
                     <img src="https://via.placeholder.com/50?text={{$singleActivity->causer->name[0]}}">
                 </span>
                 <div class="body clearfix">
                     <div class="header">
                         <strong>{{$singleActivity->causer->name }}:</strong>
                         {{$singleActivity->description}}

                         <small class="pull-right">
                             <i class="fa fa-clock-o fa-fw"></i>
                             {{$singleActivity->created_at->diffForHumans()}}
                         </small>
                     </div>
                     @if($singleActivity->properties)
                         <p>Atrybuty:
                             @foreach($singleActivity->properties as $properties)
                                 <b>{{$properties['key']}}</b>: {{$properties['new']}}
                                 @if(isset($properties['old']))
                                     z {{$properties['old']}}
                                 @endif
                                 <br>
                             @endforeach
                         </p>
                     @endif
                 </div>
             </li>
        @endforeach
    @endif
</ul>

Więcej informacji na ten temat w dokumentacji.