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

alizharb/laravel-hooks

Laravel Hooks provides a simple action/filter system for Laravel apps, letting you register and run hooks to extend packages and application code without modifying the original source. Ideal for modular, maintainable customizations.

View on GitHub
Deep Wiki
Context7

Getting Started

Laravel Hooks is an extensibility engine for Laravel that lets you attach, discover, and execute behavior around events, models, and Blade views without touching package source. With v1.2.0 it now spans hooks, Eloquent model extensions, Blade fallbacks, and DTO-typed payloads.

Minimal setup:

  1. Install and publish config: composer require alizharb/laravel-hooks then php artisan vendor:publish --tag=hooks-config.
  2. Register a listener/hook class — either via the config discovery paths or by explicitly binding with Hook::on('name', Listener::class).
  3. Clear cached discovery between changes: php artisan hooks:clear (or your configured cache command) — this is the most common "why isn't my hook firing" fix.

First use case to reach for: wrapping an existing feature with a hook so downstream apps can override behavior. E.g. drop a Hook::on('order.created') call in your service, then let other packages or app code subscribe. Run php artisan hooks:list (or the debug command) to confirm discovery.

If you're coming from v1.1.x, audit any hooks on hot paths before deploying — the Circuit Breaker in v1.2.0 can silence listeners automatically (see Gotchas).

Implementation Patterns

Attribute-driven Eloquent extensions. For day-to-day use, the killer feature is #[DynamicRelation], #[DynamicCast], and #[DynamicScope] on listener classes. You can add a latestOrder relation or a isActive scope to a vendor model (e.g. User) without a migration or fork:

#[DynamicRelation(model: User::class, name: 'latestOrder')]
public function latestOrder(User $user) {
    return $user->hasOne(Order::class)->latestOfMany();
}

Prefer this for additive behavior on models you don't own. Reach for the fluent API (Hook::model(User::class)->addRelation(...)) inside a service provider when you need conditional logic (e.g. only in non-production or behind a feature flag).

HasDynamicHooks trait. Reserve this for models where you genuinely need interception — dynamic methods and attribute filtering. It's powerful but adds magic; use it on your own models, not as a default on every model.

Type-safe DTOs. New in 1.2.0 — declare a hook signature with a DTO, and the package validates the payload automatically:

Hook::on('order.created', function (OrderCreatedDTO $dto) { ... });

This is the cleanest way to evolve an internal hook contract. Define the DTO in your app (or a shared package), version it, and let the framework reject malformed payloads at dispatch instead of deep in a listener.

Circuit breaker for integrations. Wrap third-party calls (webhooks, mail providers, external APIs) in a hook and let the breaker mute flaky listeners after N failures. Configure threshold + cooldown in config/hooks.php. Use it for anything non-critical; do not put critical business logic behind a hook you're willing to auto-silence.

Blade fallbacks. @hook('sidebar.widgets', 'fallbacks.sidebar') avoids the "empty UI in a fresh install" problem. Ship a sensible fallback view alongside every optional widget hook.

Modular integration. Zero-config with laravel-modular via modules_path() discovery. If you're already on that stack, no extra registration needed — hooks in module listeners get picked up.

Gotchas and Tips

  • Circuit breaker hides bugs. A silenced hook returns null/skips silently by default. In staging, log breaker trips loudly and consider disabling the breaker (threshold 0 or off flag) so you catch regressions that would otherwise vanish in production.
  • Discovery caching. New attribute-based extensions and fluent bindings are cached. After adding #[DynamicRelation] or changing DTO signatures, run the cache clear. Symptom: "my hook works in tinker but not in the app."
  • DTO strictness is a feature and a trap. A DTO signature means any caller sending an array or the wrong DTO gets rejected. When you add a DTO to an existing hook, treat it as a breaking change for downstream subscribers.
  • Dynamic model metadata is cached separately. If you change relations/scopes at runtime (feature flags, tenancy), invalidate that cache explicitly or scope the extension to request lifetime.
  • Blade multi-line parsing improved but isn't perfect. The auto-documentation engine now handles multi-line @hook calls, but unusual formatting or concatenated view names may still be missed. Keep @hook calls on clean, single-name lines when documentation matters.
  • Don't stack dynamic extensions across packages. Two packages adding a #[DynamicRelation] with the same name on the same model will conflict; pick namespaced relation names (e.g. billing_latestOrder).
  • Pulse / Debugbar. Use the new snapshots to eyeball hook timing before enabling the breaker — you need a baseline to know what "failing" looks like.
  • PHPStan/CI expectations. The package targets PHPStan Level 5 and Pest on 8.3/8.4. If you mirror their standards in your consuming app, expect attribute-heavy code to need @phpstan-* hints on dynamic method calls; the trait's magic isn't statically resolved.
  • Extension points to lean on: config discovery paths, the circuit breaker threshold/cooldown config, DTO types, and Blade fallback views. All four are stable, supported customization surfaces — prefer them over subclassing internals like the discovery engine or metadata cache, which aren't guaranteed stable across minor releases.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource