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 Activatable Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package via Composer and check the README's quick-start before anything else — for a 1.0.0 with only a changelog link, the README and src/ are your only real documentation.

composer require bernskiold/laravel-activatable

If the package ships a config and migration (typical for activation-style packages that persist an activated_at / is_active column), publish and run them:

php artisan vendor:publish --tag="activatable-config"
php artisan vendor:publish --tag="activatable-migrations"
php artisan migrate

Then add the trait to any model that needs an on/off lifecycle:

use Bernskiold\Activatable\Concerns\Activatable;

class Account extends Model
{
    use Activatable;
}

First use case: gate access without deleting rows. Instead of soft-deleting a user or team, deactivate it — the record survives for auditing, relations stay intact, and reactivation is a single call. Start by verifying the trait's public API in src/Concerns/Activatable.php (method names, scope names, event names) since these are the surface you'll build on.

Implementation Patterns

Query scoping. Use the package's active scope as your default read path rather than filtering in PHP. Wrap it in a local scope or repository method so call sites don't depend on the package's exact scope name:

public function scopeVisible(Builder $q): Builder
{
    return $q->active(); // whatever the trait exposes
}

Route gating. Pair activation with a small middleware that rejects requests from deactivated principals. Keep it separate from auth so you can distinguish "not logged in" (401) from "deactivated" (403) — clients care about the difference.

Authorization vs. activation. Activation is a lifecycle flag, not a permission. Enforce it in a Gate::before or policy check in addition to your role logic, not instead of it. Models that are deactivated should fail closed everywhere.

Scheduled lifecycle. If the package supports timestamp-based activation, drive transitions from a scheduled command (php artisan schedule:run) rather than at read time. Read-time checks make list queries unpredictable and unindexable.

Admin toggles. Expose activate/deactivate as explicit actions in Filament/Nova rather than a boolean form field — you get an audit trail and avoid a raw is_active update bypassing the package's events.

Events as integration points. Listen for the activation/deactivation events to invalidate caches, revoke tokens, notify the account owner, or kick off cleanup jobs. This is the cleanest way to add behavior without forking the package.

Factory states. Add ->inactive() / ->active() states to factories immediately; nearly every test will need one.

Gotchas and Tips

  • Silent inclusion. Traits don't change queries automatically. Every listing endpoint needs the active scope or deactivated records leak into dashboards and counts — audit your all() and get() calls.
  • Global scope trap. If the package registers a global scope, deactivated records vanish from admin panels and find() lookups too. Use withoutGlobalScope(...) deliberately and document where you do.
  • Caches go stale. Any cached "is this user active?" check must be invalidated on the activation events. Short TTLs plus event-driven busting is the safe combination.
  • Queued jobs. A job dispatched before deactivation will still run. Re-check activation at the top of sensitive jobs ($this->user->isActive() or a fresh query) rather than trusting the serialized model.
  • Timezone drift. Scheduled activation comparisons are timezone-sensitive. Store UTC, compare UTC, and verify the package's cast isn't using the app timezone implicitly.
  • Mass assignment. A guard-free is_active column means a stray $request->all() in an update can activate or deactivate anyone. Keep it out of $fillable and flip it only through the package's methods.
  • Index it. Add an index on the activation column before you ship — every scoped query hits it.
  • Double events. If you also hook saved or updated observers, you'll get duplicate side effects on transitions. Pick one layer.
  • Extension points. Prefer overriding the trait's methods in your model or listening to events over editing published files; 1.0.0 is young and the internals will move.
  • Verify the API surface yourself. With only a changelog link as release notes, treat src/ as the spec. Method names, the nullable-vs-boolean storage choice, and whether scopes are global are the three details that most affect how this integrates, and none are documented in the 1.0.0 notes.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager