whilesmart/eloquent-activities

Flexible activity tracking package for Laravel applications with actor-action-subject pattern

Maintainers

Package info

github.com/whilesmartphp/eloquent-activities

pkg:composer/whilesmart/eloquent-activities

Statistics

Installs: 35

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-03-08 19:36 UTC

This package is auto-updated.

Last update: 2026-03-08 19:36:52 UTC


README

Flexible activity tracking package for Laravel applications using the Actor-Action-Subject pattern.

Features

  • Actor-Action-Subject Pattern: Track who did what to what
  • Polymorphic Relationships: Works with any Eloquent model
  • Flexible Context: Scope activities to workspaces, projects, organizations, etc.
  • Multiple Sources: Track activities from manual entry, webhooks, API, system events, and integrations
  • Rich Metadata: Store flexible properties and metadata with each activity
  • Powerful Query Scopes: Filter activities by actor, subject, context, action, source, and date range
  • Easy Integration: Simple trait to add activity tracking to any model
  • Configurable: Customize routes, middleware, and features via configuration
  • Laravel 11+ & 12+ Support: Compatible with modern Laravel versions

Installation

Install via Composer:

composer require whilesmart/eloquent-activities

Publish Configuration (Optional)

php artisan vendor:publish --tag=activities-config

Run Migrations

php artisan migrate

Quick Start

1. Add the Trait to Your Models

use Whilesmart\Activities\Traits\HasActivities;

class Task extends Model
{
    use HasActivities;

    // ...
}

2. Create Activities

use Whilesmart\Activities\Models\Activity;

// Simple activity
Activity::create([
    'actor_type' => User::class,
    'actor_id' => $user->id,
    'action' => 'created',
    'subject_type' => Task::class,
    'subject_id' => $task->id,
    'source' => Activity::SOURCE_MANUAL,
    'summary' => 'Task created',
    'description' => 'User created a new task',
    'occurred_at' => now(),
]);

// Activity with context (workspace-scoped)
Activity::create([
    'actor_type' => User::class,
    'actor_id' => $user->id,
    'action' => 'updated',
    'subject_type' => Task::class,
    'subject_id' => $task->id,
    'context_type' => Workspace::class,
    'context_id' => $workspace->id,
    'source' => Activity::SOURCE_SYSTEM,
    'summary' => 'Task updated',
    'occurred_at' => now(),
]);

// Activity with properties and metadata
Activity::create([
    'action' => 'login',
    'actor_type' => User::class,
    'actor_id' => $user->id,
    'source' => Activity::SOURCE_SYSTEM,
    'properties' => [
        'ip_address' => request()->ip(),
        'duration' => 3600,
    ],
    'metadata' => [
        'browser' => 'Chrome',
        'version' => '120.0',
    ],
    'occurred_at' => now(),
]);

3. Query Activities

// Get activities for a specific user
$activities = Activity::forActor(User::class, $user->id)->get();

// Get activities for a specific task
$activities = Activity::forSubject(Task::class, $task->id)->get();

// Get activities within a workspace context
$activities = Activity::inContext(Workspace::class, $workspace->id)->get();

// Filter by action
$activities = Activity::byAction('created')->get();

// Filter by source
$activities = Activity::bySource(Activity::SOURCE_WEBHOOK)->get();

// Filter by date range
$activities = Activity::inDateRange('2024-01-01', '2024-01-31')->get();

// Chain scopes for complex queries
$activities = Activity::forActor(User::class, $user->id)
    ->forSubject(Task::class, $task->id)
    ->inContext(Workspace::class, $workspace->id)
    ->byAction('created')
    ->latest('occurred_at')
    ->get();

4. Access Model Activities

// Get all activities for a task
$task->activities;

// Get the latest activity timestamp
$task->last_activity;

Configuration

The package provides several configuration options in config/activities.php:

return [
    // Model Configuration
    'user_model' => env('ACTIVITIES_USER_MODEL', 'App\\Models\\User'),
    'workspace_model' => env('ACTIVITIES_WORKSPACE_MODEL', 'App\\Models\\Workspace'),
    'project_model' => env('ACTIVITIES_PROJECT_MODEL', 'App\\Models\\Project'),

    // Route Configuration
    'register_routes' => env('ACTIVITIES_REGISTER_ROUTES', true),
    'route_prefix' => env('ACTIVITIES_ROUTE_PREFIX', ''),
    'route_middleware' => ['auth:sanctum'],

    // Feature Flags
    'workspace_scoped' => env('ACTIVITIES_WORKSPACE_SCOPED', true),
    'project_scoped' => env('ACTIVITIES_PROJECT_SCOPED', true),
    'allow_manual_creation' => env('ACTIVITIES_ALLOW_MANUAL', true),
    'allow_webhook_creation' => env('ACTIVITIES_ALLOW_WEBHOOK', true),
];

API Routes

If routes are enabled, the following endpoints are automatically registered:

List Activities

GET /api/activities
GET /api/workspaces/{workspaceId}/activities

Query Parameters:

  • projectId - Filter by project
  • memberId - Filter by user/member
  • from - Filter by start date
  • to - Filter by end date

Create Activity

POST /api/activities
POST /api/workspaces/{workspaceId}/activities

Request Body:

{
  "projectId": 1,
  "startTime": "2024-01-01 10:00:00",
  "summary": "Activity summary",
  "description": "Activity description"
}

Activity Sources

The package supports multiple activity sources:

Activity::SOURCE_MANUAL      // User-created activities
Activity::SOURCE_WEBHOOK     // Activities from webhooks
Activity::SOURCE_API         // Activities from API calls
Activity::SOURCE_SYSTEM      // System-generated activities
Activity::SOURCE_INTEGRATION // Activities from integrations

Check activity source:

$activity->isManual();
$activity->isFromWebhook();
$activity->isSystem();

Properties and Metadata

Store flexible data with activities:

// Set properties
$activity->setProperty('duration', 3600);
$activity->setProperty('priority', 'high');
$activity->save();

// Get properties
$activity->getProperty('duration');
$activity->getProperty('priority', 'default_value');

// Set metadata
$activity->setMetadata(['browser' => 'Chrome', 'version' => '120.0']);
$activity->setMetadata('browser', 'Chrome');
$activity->save();

// Get metadata
$activity->getMetadata();
$activity->getMetadata('browser');

Testing

Run the test suite:

composer test

Run code style checks:

composer pint:test

Fix code style issues:

composer pint

Use Cases

  • Audit Logs: Track all changes to important models
  • User Activity Feeds: Show what users have been doing
  • Workspace Activity: Track activities within workspace contexts
  • Project Timelines: Display project-related activities
  • System Events: Log important system events and actions
  • Integration Tracking: Track activities from external integrations
  • Time Tracking: Store time-related data in activity properties

Database Schema

The activities table includes:

  • actor_type/actor_id: Who performed the activity (polymorphic)
  • action: What action was performed
  • subject_type/subject_id: What entity was acted upon (polymorphic, optional)
  • context_type/context_id: The scope/context (workspace, project, etc., optional)
  • source: Where the activity originated from
  • source_id: External source identifier (optional)
  • summary: Short description
  • description: Detailed description
  • properties: Flexible JSON data
  • metadata: Additional JSON metadata
  • occurred_at: When the activity occurred
  • created_at/updated_at: Record timestamps

Requirements

  • PHP 8.2 or higher
  • Laravel 11.0 or 12.0

License

MIT License

Credits

Developed by the Whilesmart Team