- How do I replace Laravel Observers with ArtisanPack UI Hooks?
- Use `addAction('model.saved', fn($model) => {...})` instead of Observers for simpler, non-event-driven callbacks. Hooks are ideal for synchronous workflows like logging or notifications, while Observers (or Events) are better for async tasks. Prioritize hooks for modular extensions where you need predictable execution order.
- Can I use hooks for dynamic feature flags or runtime configuration?
- Yes, hooks work well for runtime configuration. Register callbacks conditionally (e.g., `if (config('features.dynamic_hook')) addAction(...)`) or use filters to modify values dynamically. For feature flags, pair with Laravel’s config cache for performance.
- What’s the performance impact of 10,000+ registered hooks?
- Benchmarking shows minimal overhead for up to 1,000 hooks, but 10K+ may slow execution. Optimize by batching callbacks (e.g., group by priority) or lazy-loading hooks in high-throughput systems. Test with `doAction('benchmark', ...)` in a loop to validate.
- How do I avoid memory leaks when removing hooks in queues or long-running processes?
- Use `removeAction()` or `removeAllActions()` to clean up callbacks explicitly. For queues, call removal in the job’s `handle()` method before exiting. Monitor memory with Laravel Debugbar or `memory_get_usage()` in critical paths.
- Are Blade directives `@action` and `@filter` secure for user-generated content?
- No, Blade directives are not secure by default. Always sanitize filter outputs with `e()` or `htmlspecialchars()` to prevent XSS. Example: `@filter('user.name', $name, 'e')` ensures safe rendering. Avoid dynamic hook names in Blade.
- How do I namespace hooks to prevent collisions (e.g., `auth.login` vs. `auth.login.success`)?
- Use kebab-case for hook names (e.g., `auth.login`, `payment.processed`) and document your namespace conventions. For plugins, prefix with the package name (e.g., `plugin-name.hook`). Avoid generic names like `user.created` if multiple packages might use them.
- Should I use facades (`Action::do()`) or helper functions (`doAction()`) in my project?
- Facades are useful for global state (e.g., `Action::do('app.initialized')`), while helper functions are lighter for local scope. Teams new to Laravel may prefer facades for consistency with existing code. Benchmark both—facades add negligible overhead.
- How do I test hook-based logic in Pest or PHPUnit?
- Mock `doAction()` or `applyFilters()` using Pest’s `spies` or PHPUnit’s `partialMock`. Example: `spy(doAction('test.hook'))->wasCalledWith($expectedArg)`. Test removal with `assertNull(removeAction(...))`. Use `HooksServiceProvider::reset()` to clear hooks between tests.
- Can I use hooks for HTTP middleware-like behavior (e.g., modifying requests/responses)?
- Yes, but middleware is still better for auth/CSRF. Use `addAction('kernel.handle', fn($request) => {...})` for request modifications or `addFilter('response.content', fn($content) => {...})` for response tweaks. Hooks lack middleware’s built-in termination logic.
- What’s the difference between hooks and Laravel Events for async workflows?
- Hooks are synchronous and prioritized, while Events support async listeners (queues, broadcasts). Use Events for background jobs (e.g., sending emails) and hooks for immediate, modular extensions (e.g., logging). Combine both: dispatch an Event *after* `doAction('order.processed')`.