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

Hookable Laravel Package

sofa-support/hookable

Hookable adds a lightweight hook system to Laravel Eloquent models, letting you register callbacks that run before or after events like create, update, and delete without scattering logic across observers. It keeps model behavior tidy, composable, and easy to test.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit sofa-support/hookable is a thin behavioral extension over Eloquent's model lifecycle. It does not introduce a new architectural layer; it occupies the same seam as Laravel's native model events and observers, adding per-model hook registration with explicit priority ordering and abort semantics. Fit is good only if our domain models are already the intended home for lifecycle behavior. If our target architecture pushes business rules into actions/services, this package actively encourages logic to accumulate in the persistence layer, which is a design regression we would have to govern against. The sofa/* idiom (Sofia CMS lineage) matches a specific era of Laravel codebases; it will feel native in a legacy model-centric app and foreign in a modern action-oriented one.

Integration feasibility Low-effort to evaluate: a single Composer require, one trait on the model, and optionally facade-based registration in a service provider. No migrations, no external services, no infrastructure. A credible spike is 0.5–1 day across two or three representative models. The offsetting cost is that with zero dependents there are no reference implementations, no downstream compatibility evidence, and no community patterns to copy — every integration decision is ours to validate.

Technical risk The dominant risk is lifecycle, not code quality. Last release was December 2020, 65 stars, a single maintainer, zero dependents, and an opportunity score of 2.16 — all signals that upstream is dormant and native alternatives dominate. Concretely: the illuminate/* constraints will almost certainly block Laravel 9/10/11 upgrades without a fork, and PHP 8.1+ deprecations (dynamic properties, missing return types) are unaddressed. Behavioral risk is subtler — hook execution interacting with SoftDeletes, $touches, booted() trait methods, and observers registered in providers is undocumented territory we would be the first to map.

Key questions

  • Which hook points exist, and how does each map one-to-one onto native saving/saved/creating/deleting events? Where is the marginal capability beyond native events?
  • What is the abort contract — does returning false halt the operation, throw, or silently no-op?
  • Are priority semantics deterministic when hooks are registered from both the model property and the facade?
  • Do hooks fire on mass query()->update() / ->delete() calls, or are they silently bypassed like native events?
  • Is the hook registry a process-wide singleton, and can it be reset between tests and queue jobs?
  • Is there a published version/compatibility matrix, and what is our exit cost if upstream stays dark?

Verdict: the package's differentiated value over native observers is narrow (priority ordering plus centralized registration). Given the abandonment profile, the default should be "do not adopt as a dependency"; adopt the pattern via a small internal trait or fork.

Integration Approach

Stack fit Targets the PHP 7.x–8.0 / Laravel 6–8 window. On Laravel 10/11 with PHP 8.2+ we should assume constraint edits and a maintained fork are prerequisites, not contingencies. Best fit is a model-centric or legacy application undergoing incremental modernization, where introducing ordered hooks is cheaper than refactoring observers.

Migration path Introduce alongside native observers rather than replacing them. Put the trait on a deliberately small set of models first, and wrap existing observer logic so it delegates through the hook layer — this creates a reversible switch and lets us diff behavior model-by-model. Do not blanket-apply the trait to the whole model graph; the blast radius of a lifecycle change on a shared base model is the single largest integration hazard here.

Compatibility Audit against our PHP/Laravel support matrix before any code is written: Composer constraints, deprecation notices under our PHP version, and interaction with SoftDeletes, $touches, timestamps, and providers that register observers. Critically, verify that the hook registry can be flushed — Laravel's RefreshEventDispatcher knows nothing about it, so leaked registrations will produce order-dependent test failures and cross-job contamination in queue workers.

Sequencing

  1. Spike on a branch with 2–3 representative models, including one with soft deletes and one with related-model writes.
  2. Make the build-vs-fork call and record it as an ADR with explicit exit criteria (e.g., "fork if upstream is untouched at our next Laravel major").
  3. If adopted, pin to a commit and vendor the fork under our org namespace — the code footprint is small enough that ownership cost is trivial.
  4. Roll out per bounded context, lowest-criticality first, with each context gated on its own test coverage.
  5. Publish the convention (who may register hooks, where they live, what is forbidden inside one) before the second team onboards.

Operational Impact

Maintenance Treat this as an internally owned component from day one. Expect 1–2 engineer-days per Laravel major upgrade for constraint and deprecation work, plus unplanned effort whenever Eloquent internals shift. Because the code is small, vendoring converts an open-ended dependency risk into a bounded, well-understood maintenance line item — that is the strongest argument for fork-over-require.

Support No vendor support, no SLAs, minimal community surface. With 65 stars, Stack Overflow and issue-search yields will be near zero, so internal documentation is the only support channel. Budget for a short internal README covering hook points, abort semantics, and ordering rules; without it, tribal knowledge becomes the failure mode.

Scaling Hooks are synchronous and in-process, so per-call overhead is negligible. The real scaling concern is composition: a hook that saves a related model can cascade into further hooks, multiplying write cost and lengthening transactions on hot tables. Establish a hard rule that hooks perform no external I/O — mail, HTTP, and queue dispatch belong in after-commit jobs. Priority ordering is deterministic within a registry but invisible at runtime; add structured logging or metrics around hook execution so ordering conflicts are diagnosable rather than inferred.

Failure modes

  • Silent non-firing on mass updates and deletes, producing data-integrity gaps that surface much later.
  • Exceptions thrown mid-hook inside an open transaction, leaving partial writes unless the caller wraps and rolls back.
  • Re-entrancy and infinite loops when a hook persists a related model that itself carries hooks.
  • Registry state leaking across tests and long-lived queue workers, causing order-dependent, non-reproducible bugs.
  • Priority conflicts between teams editing the same registry, resolved only by whoever registered last.
  • A dormant upstream blocking a framework upgrade at the worst possible moment, forcing an emergency fork.

Ramp-up Individual ramp-up is under a day for a mid-level Laravel developer — the API surface is small and familiar. The genuine ramp-up is social: agreeing on what a hook is and is not allowed to do, where hook registrations live in the codebase, and how they are reviewed. Allocate one or two hours of team documentation plus a PR checklist item ("does this change hook ordering or abort behavior?") and treat that as mandatory onboarding, not optional polish.

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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings