bernskiold/laravel-activatable
A Laravel package that adds activatable behavior to Eloquent models. Easily activate or deactivate records, query only active or inactive entries with built-in scopes, and keep model status handling clean and consistent across your application.
Architecture fit — laravel-activatable is a conventional Eloquent behaviour package: a trait applied to models, query scopes for filtering active/inactive records, and publishable migrations that add activation state columns. This is the standard Laravel extension pattern (trait + scope + service provider with package auto-discovery), so it slots into an existing domain layer without requiring an architectural change. It is additive, not invasive: no base model replacement, no container rebinding, no middleware.
Integration feasibility — Low. Typical adoption is composer require, publish migrations, php artisan migrate, then use Activatable on target models. Effort is measured in hours per model, dominated by the data backfill decision rather than the code change.
Technical risk — Moderate, and mostly unverified rather than known-bad. The 1.0.0 release notes contain only a changelog link with no substance, so this assessment is inferred from the package's name, namespace (bernskiold) and Laravel ecosystem conventions, not from a reviewed diff. Specific unknowns: the supported Laravel/PHP version matrix, whether the trait stores state as a nullable timestamp, a boolean, or both; whether it emits events on activation/deactivation; test coverage and CI; and whether migrations are reversible. The 1.0.0 label is a stability signal for the API surface but says nothing about maturity of the maintainer's release process.
Key questions for the maintainer / spike
activated_at, boolean flag, or status enum? Is "never activated" distinguishable from "deactivated"?SoftDeletes, existing is_active columns, and global scopes?Treat the absence of a real changelog at a 1.0.0 milestone as a process signal. It is not disqualifying for a package this small, but it means the source must be read before adoption.
Stack fit — Assumes a Laravel application on Eloquent with standard migration-driven schema management. No frontend, queue, or cache surface. It composes cleanly with authorisation policies (gate access on activation state) and with admin/filament-style back offices, but the package supplies only the model layer — UI and permission semantics remain ours.
Migration path — Install behind a feature branch, publish the migrations, and inspect the generated schema before running anything against a shared database. Add the state columns as nullable, deploy the schema change independently of the code change, backfill existing rows to a deliberate default (usually "active"), then apply the trait to a single low-traffic model. Only after that pilot passes the full suite do we expand to further models.
Compatibility checks
composer.json; do not float ^1.0 until the release cadence is understood.active/activated_at fields, and for interaction with SoftDeletes on the same model.Sequencing
Maintenance — Single-maintainer, low-volume package. The realistic maintenance task is not patching but watching: track upstream commits and be prepared to fork, since a one-person project may lag on new Laravel majors. Budget a recurring review each framework upgrade.
Support — Community support via GitHub issues only; no commercial backing, no SLA. Internal knowledge will reside with whoever performs the source read, so document the schema contract and trait semantics in-repo.
Scaling — Query cost is governed by whether the state columns are indexed. A scope compiling to where activated_at is not null is cheap with an index and a sequential scan without one; on large tables that is the difference between a fast page and an incident. Also verify that any global scope does not silently reshape analytics or reporting queries, where "inactive" rows can legitimately matter.
Failure modes
update() changing state without firing observers, so audit logs and downstream jobs drift.migrate:rollback dropping state columns and destroying activation history.Ramp-up — Low for anyone fluent in Eloquent: roughly half a day to read the source and ship a pilot. The non-obvious cost is the data decision — which records count as active on day one — and that conversation belongs to the product owner, not the developer.
How can I help you explore Laravel packages today?