Installation:
composer require blast-project/utils-bundle
Ensure Blast\UtilsBundle\BlastUtilsBundle::class is registered in config/bundles.php.
Enable Hooks:
Add the Twig extension to your config/packages/twig.yaml:
twig:
extensions:
- Blast\UtilsBundle\Twig\HookExtension
First Use Case: Declare a hook in a Twig template:
{{ blast_hook('my.first.hook', {'key': 'value'}) }}
Register a hook listener in a service:
// src/Service/MyHookListener.php
namespace App\Service;
use Blast\UtilsBundle\Hook\HookInterface;
class MyHookListener implements HookInterface
{
public function handle(HookInterface $hook, array $hookParameters)
{
// Logic here
}
}
Tag the service in services.yaml:
services:
App\Service\MyHookListener:
tags:
- { name: 'blast.utils.hook', hook: 'my.first.hook' }
Hook-Based Workflows:
{{ blast_hook('footer.scripts') }}
// Listener
public function handle(HookInterface $hook, array $hookParameters)
{
return '<script>console.log("Dynamic script!");</script>';
}
Parameter Passing: Pass data to hooks for context-aware logic:
{{ blast_hook('user.profile', {'user': user, 'isAdmin': user.isAdmin()}) }}
Access parameters in the listener:
public function handle(HookInterface $hook, array $hookParameters)
{
$user = $hookParameters['user'];
// ...
}
Conditional Hooks: Use hooks to conditionally render content:
{% if blast_hook('sidebar.promotions') is not empty %}
<div class="promotions">
{{ blast_hook('sidebar.promotions') }}
</div>
{% endif %}
Choices Integration (if documented later):
Assume a BlastChoices helper for form/validation patterns:
use Blast\UtilsBundle\Choice\BlastChoices;
$choices = BlastChoices::create()
->add('option1', 'Label 1')
->add('option2', 'Label 2')
->toArray();
Service Binding:
Bind custom hook listeners as services with the blast.utils.hook tag for automatic registration.
tags:
- { name: 'blast.utils.hook', hook: 'custom.hook.name' }
Priority Handling: Order listeners by tag priority (default: 0). Higher values execute later.
tags:
- { name: 'blast.utils.hook', hook: 'my.hook', priority: 10 }
Testing Hooks:
Mock hooks in tests using the HookInterface:
$hook = $this->createMock(HookInterface::class);
$hook->method('getName')->willReturn('test.hook');
$listener->handle($hook, ['param' => 'value']);
Hook Naming Collisions:
Avoid generic hook names (e.g., header, footer) to prevent unintended overrides. Use namespaced hooks like app.header.custom.
Parameter Type Safety: Hook parameters are passed as raw arrays. Validate types in listeners:
if (!isset($hookParameters['user']) || !$hookParameters['user'] instanceof User) {
throw new \InvalidArgumentException('Invalid user parameter');
}
Circular Dependencies: Hook listeners should avoid calling other hooks recursively to prevent infinite loops.
Twig Extension Registration:
If hooks don’t render, verify the HookExtension is loaded in Twig’s extensions list.
Missing Documentation:
The BlastChoices feature lacks docs. Assume it’s experimental or undocumented until clarified.
Hook Not Firing: Check:
services.yaml.Listener Not Triggered:
Use Symfony’s debug toolbar or dump() to verify the hook is called:
{{ dump(blast_hook('debug.hook')) }}
Parameter Issues: Log parameters in the listener to debug:
error_log(print_r($hookParameters, true));
Hook Organization:
Group related hooks with prefixes (e.g., user.profile.*, checkout.*) for better maintainability.
Default Hook Content: Provide default content in listeners:
public function handle(HookInterface $hook, array $hookParameters)
{
return $hookParameters['content'] ?? 'Default content';
}
Performance: For hooks with heavy logic, consider lazy-loading or caching results if the hook is called frequently.
Extending the Bundle:
Override the HookManager service to add custom logic:
services:
blast.utils.hook.manager:
class: App\Service\CustomHookManager
decorates: 'blast.utils.hook.manager'
Choices Workaround:
If BlastChoices is needed urgently, inspect the bundle’s source for patterns or create a feature request. Example fallback:
$choices = ['key1' => 'Value 1', 'key2' => 'Value 2'];
How can I help you explore Laravel packages today?