artisanpack-ui/hooks
WordPress-style actions and filters for Laravel. Register callbacks on named hooks and filter values with helper functions, Facades, and Blade directives. Predictable priority order, auto-discovery, and support for removing specific or all callbacks.
Installation:
composer require artisanpack-ui/hooks
No manual configuration needed—Laravel’s package discovery handles registration.
First Use Case: Trigger an action in a controller:
use function doAction;
// Dispatch an action with payload
doAction('user.created', $user);
Where to Look First:
Modular Extensibility:
// In a package's service provider
addAction('app.package.initialized', fn () => $this->boot());
addFilter('auth.login.message', fn ($message) => "Welcome, {$message}");
Priority-Based Execution:
addAction('order.processed', fn () => logger('Early step'), 5);
addAction('order.processed', fn () => logger('Default step'), 10);
Blade Integration:
@action('view.rendered', $post)
@filter('title.display', $post->title)
Dynamic Hook Management:
if (config('features.email_notifications')) {
addAction('order.placed', fn ($order) => sendEmail($order));
} else {
removeAllActions('order.placed');
}
boot() for lazy loading:
public function boot(): void
{
Action::add('app.started', [$this, 'handleAppStarted']);
}
public function handle($request, Closure $next)
{
doAction('middleware.executed', $request);
return $next($request);
}
removeAllActions()/removeAllFilters():
removeAllActions('test.hook');
Action::add('test.hook', fn () => $this->assertTrue(true));
Callback Reference Equality:
removeAction()/removeFilter() require exact callable references (closures must be identical):
$callback = fn () => logger('test');
addAction('hook', $callback);
removeAction('hook', $callback); // Works
removeAction('hook', fn () => logger('test')); // Fails (new closure)
Priority Collisions:
Blade Directive Scope:
@action/@filter directives only work in Blade templates. Avoid using them in non-Blade contexts (e.g., API responses).Memory Leaks:
removeAllActions('hook.name'); // Cleanup
Action::getCallbacks('hook.name') or Filter::getCallbacks('hook.name') to debug registered callbacks (requires extending the package or using reflection).addAction('hook', fn () => logger('Priority: ' . debug_backtrace()[0]['args'][2]));
// Extend the Action class
class CustomAction extends Action {
protected static function storage(): array { return cache()->rememberForever('hooks', fn () => []); }
}
BladeDirectiveServiceProvider:
php artisan vendor:publish --provider="ArtisanPackUI\Hooks\BladeDirectiveServiceProvider"
$this->app->bind('Action', fn () => new CustomAction());
Action and Filter. Override in config/app.php if needed:
'aliases' => [
'Action' => ArtisanPackUI\Hooks\Facades\Action::class,
],
removeAllFilters() to disable them.How can I help you explore Laravel packages today?