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

Laravel Tracker Laravel Package

rezaamini-ir/laravel-tracker

Laravel Tracker is a lightweight package for monitoring activity in your Laravel application. It records tracked events and stores them for review, giving you a simple way to keep an audit trail and better understand what is happening inside your app.

View on GitHub
Deep Wiki
Context7

Getting Started

Before you install anything, verify it runs on your stack. The last tagged release is from January 2021, which predates Laravel 9, 10, and 11. Check the package's composer.json (via composer show rezaamini-ir/laravel-tracker --all or the repo) for its illuminate/* constraint and PHP requirement. If it pins ^7.0|^8.0, expect to either (a) install with --ignore-platform-reqs and test heavily, or (b) fork it and bump the constraints yourself. Don't plan a feature on it until a scratch project boots and writes a row.

Minimal path once compatibility is confirmed:

  1. composer require rezaamini-ir/laravel-tracker
  2. If the service provider isn't auto-discovered (fine on Laravel 5.5+), register it in config/app.php.
  3. php artisan vendor:publish --provider="RezaaminiIr\Tracker\...ServiceProvider" to get the config file and the migration.
  4. Read the config before migrating — table names, the columns it records, and any enabled/model-list switches are usually set here.
  5. php artisan migrate.
  6. Attach the package's trait to a model (exact trait name is in the README — typically something like Trackable) and save a record in tinker.

Your first real use case: pick your most-edited model (a Post, Order, Product), turn tracking on it, and confirm you get an audit row per create/update/delete with the changed attributes and the acting user. That single model is your canary for whether the package behaves in your app before you roll it out.

Where to look first: the migration file. It is the clearest statement of what the package actually stores (column names, JSON vs. per-field rows, indexes, foreign keys). Read it before you read the README; it tells you more about the package's capabilities — and its indexing/performance posture — than the docs usually do.

Implementation Patterns

Wrap the package behind your own interface. Given the bus factor and staleness, do not let RezaaminiIr\Tracker\... classes leak into controllers and Blade views. Create an ActivityLogger/AuditService contract and an adapter implementation that delegates to the package. When you eventually migrate to spatie/laravel-activitylog or owen-it/laravel-auditing (both actively maintained), you swap one adapter class instead of grepping the codebase.

Trait-per-model, not blanket. Apply the trackable trait to the handful of models where change history is a real requirement (financial records, content with editorial workflow, permission-bearing entities). Enabling it globally via config on a large schema inflates write volume and the audit table fast, and most models don't need it.

Query the audit table like a first-class domain table. Typical day-to-day reads:

  • Timeline for a record: filter by model_type + model_id, order by created_at.
  • "Who changed this and when": join to users on the recorded causer id.
  • Field-level diff: decode the stored JSON (or read the per-field rows) and diff against the previous row.

Build these as query scopes on your own Activity model (point it at the package's table) rather than repeating raw queries — it keeps you insulated from column-name changes and makes it testable.

Pair it with observers/service layer for intent. Raw snapshots tell you what changed; they rarely tell you why. Record a reason/message as a custom column or a separate note table and write it from your action classes. Example pattern: DB::transaction(function () { $order->update([...]); Activity::note('Refund processed by support'); }) — the tracking row and the domain change commit or roll back together.

Admin UI. The most common leverage is a "history" tab on a detail page. Because everything is a table, you can paginate it, render a "field: old → new" list, and filter by user/date without touching the write path. Cache the column-label map (DB column → human label) rather than hard-coding it in Blade.

Backfill deliberately. If you turn tracking on for an existing table, the audit table starts empty. Don't try to reconstruct history; instead set expectations (a "tracking enabled as of {date}" note) or write a one-off command that seeds initial snapshots from current state.

Testing. Use RefreshDatabase, and write your own assertion helper (e.g. assertActivityRecorded($model, 'updated')) so your tests don't depend on the package's internal API. Add one explicit test that a rollback leaves no orphan audit row.

Gotchas and Tips

The biggest gotcha is abandonment. 12 stars, one maintainer, last release 2021-01-03, no signs of active maintenance. Treat it as vendored source, not a dependency. Fork it under your org, pin the fork, and budget for maintenance — or skip it. For a new project, seriously evaluate spatie/laravel-activitylog or owen-it/laravel-auditing first; the cost of adopting an unmaintained package is usually paid later, at the worst time, during a framework upgrade.

Framework and PHP drift. Laravel 9+ removed/altered enough internals that 2020-era service providers and model traits can break silently. Symptoms: provider not registered, trait methods never called, Class not found on Str/Arr helpers, or type errors under PHP 8+ (notably around array/Jsonable return signatures). Run the full test suite, not just a smoke save.

Migration collisions. Published migrations are timestamped by the package, not by you. If you already have an activities/audits/trackers table, or run a multi-tenant setup, you'll get a clash. Rename the table in config and the migration before running, or you'll be hand-editing production schema. On multi-tenant DBs, confirm the audit table goes in each tenant DB — not just the central one — and that the causer id resolves correctly per tenant.

Event coverage is narrower than you think. Bulk updates (Model::where(...)->update()), insert(), and raw DB::statement() bypass model events entirely and will not be tracked. Same for saveQuietly()/withoutEvents(). If your app does bulk writes, tracking silently misses them — audit the write paths, don't assume.

Auth resolution edge cases. Causer id is usually pulled from auth()->id() at write time. That means: queue jobs and console commands record null; Sanctum/API guards may need explicit config; impersonation (Auth::login($other)) records the impersonated user unless you pass causer explicitly. Decide and document the policy.

Table growth and pruning. Audit tables grow monotonically and are usually the largest non-domain table within a year. Check whether the package ships a prune command (most of this vintage don't) — if not, write your own scheduled php artisan tracker:prune --days=365 command early, and make sure the table has indexes on (model_type, model_id), created_at, and causer_id/user_id. Without those, the "history" tab will be a slow query on a 5M-row table.

JSON payloads and searchability. If changes are stored as a single JSON blob, WHERE JSON_EXTRACT(payload, '$.status') = 'paid' is awkward and often unindexed. Know your storage shape before you build features on top; if you need field-level queries, that's a strong argument to switch packages.

Debugging checklist when tracking "doesn't work":

  1. Is the trait actually on the model (class_uses_recursive)?
  2. Is the table name in config the one that exists?
  3. Are events firing at all — add a saved listener that dd()s to isolate the tracker vs. the model?
  4. Is the model in a $guarded/mass-assignment path that skips events?
  5. Does a manual tinker save produce a row? If yes, the problem is your write path, not the package.

Extension points to lean on. Config-driven table/column names and a custom causer resolver (if offered) are your main levers. If the package doesn't expose a resolver, add one in your adapter rather than forking immediately — a thin wrapper that writes causer id itself is often cleaner than patching vendor code.

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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle