A while ago when I was working on a medium-size CRM-system I stumbled into a serious issue. First of all I had to log every single activities from each users in the system. Every time something new happened.

before traits and in the old times I used do like this. EACH time i wanted to create/update & delete. Imagine pasting this code +100 times in different files in a medium-size systemπŸ€¦β€β™‚οΈ Β 

// log case 
AuditLog::create([
    'name'          =>  'New case',
    'case_id'       =>  $storeCase->id,
    'user_id'       =>  $sellerID,
    'url_path'      =>  $log_url_path,
    'log_status_id' =>  Helpers::getLogStatus('new_case')
]); 

// log new user  
AuditLog::create([
    'name'          =>  'User has been created',
    'case_id'       =>  0,
    'user_id'       =>  $userID,
    'url_path'      =>  $log_url_path,
    'log_status_id' =>  Helpers::getLogStatus('new_user')
]); 
DON'T DO THIS!!

Luckily I knew that there had to be other ways to log activities. And I discovered Traits & Polymorphic in Laravel. Very powerful.

My trait is triggered each time a user create, update or delete anything within a specific model. I also choose to store data in json.

<?php
namespace App\Traits;

use Illuminate\Database\Eloquent\Relations\morphMany;
use App\AuditLog;

use Auth;

trait AuditLogger
{
    public static function bootAuditLogger(): void
    {
        static::created( static function($model){
            self::returnData($model, "Oprettede");
        });

        static::updating(static function($model){
            self::returnData($model, "Opdaterede");
        });

        static::deleted(static function($model){
            self::returnData($model, "Slettede");
        });
    }

    /**
     * Return modelName
     */
    public static function  returnData($model, string $message): object
    {
        $modelName  = $model->getClassName();
        $tableName  = $message." ".$model->getTableName();

        return $model->audits()->create(self::getAudit($model->attributes, $modelName, $tableName));
    }

    /**
     * Return data
     */
    public static function getAudit(array $attributes, string $modelName, string $tableName): array
    {
        return [
            'message' => $tableName,
            'user_id' => ((Auth::check()) ? Auth::user()->id:0), 
            'data' => json_encode($attributes, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE)
        ];
    }

    /**
     * Return model tableName
     */
    public static function getTableName(): string
    {
        return ((new self)->getTable());
    }

    /**
     * Return className
     */
    public function getClassName(): string
    {
        return (new self)->getMorphClass();
    }

    /**
     * Return morphMany
     */
    public function audits(): morphMany{
        return $this->morphMany(AuditLog::class, 'auditable');
    }
}
?>
Trait for log data

Now I'm able to use my Trait within other classes like this. No more adding functions after a submit just for tracking logs.

class User {
 
  use AuditLogger;
 
}
That's it! πŸ‘