recordActivity('created', null, $model->getAttributes()); }); static::updated(function ($model) { // Get only the fields that actually changed $newAttributes = $model->getChanges(); // Ignore the 'updated_at' timestamp noise unset($newAttributes['updated_at']); if (!empty($newAttributes)) { $oldAttributes = array_intersect_key($model->getOriginal(), $newAttributes); $model->recordActivity('updated', $oldAttributes, $newAttributes); } }); static::deleted(function ($model) { $model->recordActivity('deleted', $model->getAttributes(), null); }); } protected function recordActivity($action, $oldData = null, $newData = null) { // Define sensitive fields to NEVER log $hiddenFields = ['password', 'preshared_key', 'remember_token']; // Allow models to define custom fields to ignore via a protected $ignoreLogs array if (property_exists($this, 'ignoreLogs')) { $hiddenFields = array_merge($hiddenFields, $this->ignoreLogs); } $cleanOld = $oldData ? collect($oldData)->except($hiddenFields)->toArray() : null; $cleanNew = $newData ? collect($newData)->except($hiddenFields)->toArray() : null; ActivityLog::create([ 'user_id' => Auth::id(), 'loggable_type' => get_class($this), 'loggable_id' => $this->id, 'action' => $action, 'old_data' => empty($cleanOld) ? null : $cleanOld, 'new_data' => empty($cleanNew) ? null : $cleanNew, 'ip_address' => request()->ip(), 'user_agent' => request()->userAgent() ]); } // Helper to fetch logs for a specific model instance public function activityLogs() { return $this->morphMany(ActivityLog::class, 'loggable')->latest(); } } ?>