Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Tomato User Activities Module Laravel Package

tomatophp/tomato-user-activities-module

A TomatoPHP module that logs and displays user activities in your Laravel app, giving admins a clear timeline of actions and events for auditing and monitoring.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is tomatophp/tomato-user-activities-module, a first tagged release (v1.0.0, March 2024) with no real release notes. That means the source in vendor/ is your documentation — budget a half-day to read it before writing feature code on top of it.

1. Install and confirm discovery.

composer require tomatophp/tomato-user-activities-module

TomatoPHP modules register via Laravel package auto-discovery. Verify the provider loaded before you debug anything else:

php artisan package:discover -v
php artisan about   # look for the provider in the loaded list

If it's not listed, add the provider manually to bootstrap/providers.php (or config/app.php on older Laravel) using the class you find in the package's composer.json extra.laravel.providers block.

2. Publish config and migrations, then read them before running.

php artisan vendor:publish --tag=tomato-user-activities-module-config
php artisan vendor:publish --tag=tomato-user-activities-module-migrations

Run php artisan vendor:publish with no tag first to list what this version actually exposes — TomatoPHP tag naming drifts between modules, and a wrong tag silently publishes nothing. Open the published migration and note the columns: user_id, IP, user agent, timestamps, and any subject/polymorphic columns. Then:

php artisan migrate

3. Register the Filament plugin (if you want the admin browsing UI). In your panel provider:

->plugin(\TomatoPHP\UserActivitiesModule\UserActivitiesPlugin::make())

4. Locate the recording mechanism. Open vendor/tomatophp/tomato-user-activities-module/src and start at the service provider's register()/boot(). Look for Traits/, Models/, Listeners/, Observers/, and Middleware/. Whichever of those the provider wires up is your integration point.

First use case to prove it works end to end: log in as a test user, edit a record, then open the "User Activities" page the plugin registers in Filament. Confirm you see your user_id, the IP, the action, and a timestamp. If the row is missing, work backwards: model → listener/middleware → provider boot → config cache. That one round trip tells you more than the README.

One feature worth testing early: the package's description mentions each request being tagged with a request hash that you can correlate against standard Laravel logs. If a middleware is registered for this, drop a Log::info('...') in a controller and check whether the same hash appears in both the log line and the activity row. That correlation is genuinely useful during incident triage and it's cheap to verify.

Implementation Patterns

Record at the boundary, not in controllers. If the package ships middleware, register it globally or on authenticated route groups in bootstrap/app.php / Kernel.php. If it ships a trait or observer, attach it to User and to the specific models you actually want audited — not AppServiceProvider::boot() over every model. Blanket application is the fastest way to a table you can't query and a page that takes four seconds to load.

Queue writes off the request path. Every activity row is an insert on the hot path. If the package exposes a config toggle for queuing, turn it on. If not, and your traffic is meaningful, register your own ShouldQueue listener against the events you care about and keep the vendor's synchronous path for the low-volume cases. On a login-heavy or API-heavy app, this is the difference between a 2ms overhead and a 40ms one.

Compose with spatie/laravel-activitylog rather than replacing it. This module is a user activity layer — who was doing what, from where. Spatie handles model-level before/after diffs. They answer different questions and coexist fine. If you need both, decide which table is authoritative for which question before you build dashboards on top, otherwise you'll have two sources of truth and no clear answer when they disagree.

Point dashboards at the module's widgets; don't rebuild the table. The Filament widget is the main reason to use this over a hand-rolled table. If you need extra columns or tenant scoping, subclass the widget and swap it in your panel provider — keep vendor/ untouched so composer update stays clean.

Resolve the guard explicitly in multi-guard apps. If you have separate web and admin guards, confirm which one the module reads from. Most TomatoPHP modules default to config('auth.defaults.guard'). If your admin panel authenticates against a different guard, every activity row will have a null or wrong user_id and the UI will look empty. Set it in the published config and write a test that asserts the causer is correct under the non-default guard.

Plan retention on day one. This table grows monotonically. Add pruning to your schedule immediately:

// routes/console.php or app/Console/Kernel.php
Schedule::command('model:prune', [
    '--model' => [\TomatoPHP\UserActivitiesModule\Models\UserActivity::class],
])->daily();

If the vendor model doesn't implement Prunable, subclass it, add the trait plus a prunable() query scoped to your retention window (e.g. ->where('created_at', '<', now()->subDays(90))), and bind your subclass wherever the module resolves the model.

Wrap access behind your own interface. Create a thin ActivityRepository or query object in your app that the Filament page, any API endpoint, and any export all go through. This costs an hour and buys you a one-file swap if the package stalls or you outgrow it — which, at v1.0.0 with zero dependents, is a live possibility.

Testing. Use RefreshDatabase. Assert against the package model directly, never against rendered Filament tables — Blade changes between patch releases and your tests will break for no reason. Freeze time with travelTo() before asserting timestamps; activity rows are timestamp-sensitive and flake otherwise.

it('records a login activity', function () {
    $user = User::factory()->create();
    $this->actingAs($user)->post('/login');

    expect(UserActivity::where('user_id', $user->id)->exists())->toBeTrue();
});

Gotchas and Tips

  • Pin the version. "tomatophp/tomato-user-activities-module": "^1.0" in composer.json, and read the diff of src/ on every minor bump. There is no documented upgrade path, and the v1.0.0 note is a changelog link with nothing described.
  • Filament major-version coupling is the top breakage risk. Check composer.json in the package for whether this tag targets Filament v3 or v4 before installing into an existing panel. A mismatch surfaces as a confusing "class not found" in your panel provider, not as a clean dependency conflict — you'll spend an hour in the wrong file.
  • Inspect indexes before going to production. The Filament table filters on user_id, event/action, and created_at. If those columns lack indexes, the page will crawl within a few months of real traffic. Add your own migration for missing indexes; don't edit the vendor one, or composer update will clobber it.
  • php artisan config:clear after publishing config. A config cache from before install makes the plugin do nothing at all, which reads exactly like a broken package. Clear the cache before you start debugging the code.
  • PII and retention are your problem, not the package's. IP addresses and user agents are personal data under GDPR. Decide up front whether you store them, for how long, and whether they belong in your production database at all. If there's no config toggle, override the model or add a redaction step in your own listener — do it before the first production deploy, not after the first customer request.
  • Timezone drift in the UI. Filament renders in the panel timezone; your DB stores UTC. If "last activity" looks hours off, check the panel's ->timezone() setting before touching the module.
  • Run php artisan filament:assets after install if the module ships views or JS. Otherwise the page renders blank with no error in the log — the classic silent-failure trap.
  • Correlate the request hash into your own logs. If the module exposes a request hash, add it to your log context (a small middleware pushing Log::withContext(['request_hash' => ...]) is enough). That single line turns "user says it broke at 2pm" into a filtered query.
  • Extension point to prefer, in order: subclass the model/widget → bind your subclass in config → publish and modify views as an absolute last resort. Modified published Blade files become upgrade friction the moment v1.1.0 lands.
  • When something breaks, read vendor/tomatophp/tomato-user-activities-module/src, starting at the service provider. With thin docs and a single-author maintainer, that file is the spec. Trace boot() outward and you'll find the answer faster than any search.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums