sylius/twig-hooks
Sylius Twig Hooks is a lightweight component from the Sylius Stack initiative that adds a hook-based extension system for Twig templates, making it easier to customize and extend views in a structured, decoupled way.
Installation Add the package via Composer:
composer require sylius/twig-hooks
Register the TwigHooksExtension in your config/packages/twig.php:
twig:
extensions:
- Sylius\Component\Twig\Hooks\TwigHooksExtension
First Hook Usage Define a hook in your Twig template:
{% hooks 'hook_name' %}
Register a hook in your controller or service:
$this->twigHooks->addHook('hook_name', 'template_path');
Basic Example In a controller:
public function showAction(Request $request)
{
$this->twigHooks->addHook('product_page_header', 'product/_partials/header.html.twig');
return $this->render('product/show.html.twig');
}
Sylius\Component\Twig\Hooks\TwigHooksExtension and HooksNode for core logic.Dynamic Layouts Use hooks to modularize templates without inheritance:
{% hooks 'sidebar' %}
{% hooks 'footer' %}
Conditional Hooks Register hooks conditionally in controllers:
if ($user->isAdmin()) {
$this->twigHooks->addHook('admin_toolbar', 'admin/_toolbar.html.twig');
}
Hooks with Data
Pass variables to hooks via addHookWithData:
$this->twigHooks->addHookWithData(
'product_extra_info',
'product/_partials/extra_info.html.twig',
['attributes' => $product->getAttributes()]
);
Global Hooks Register hooks globally in a service (e.g., event subscriber):
public function onKernelRequest(GetResponseEvent $event)
{
$this->twigHooks->addHook('global_header', 'shared/_header.html.twig');
}
{% cache 'hook_product_sidebar_' ~ product.id %}
{% hooks 'product_sidebar' %}
{% endcache %}
Hook Order
Hooks are rendered in the order they are added. Use addHookFirst to prepend:
$this->twigHooks->addHookFirst('hook_name', 'template_path');
Missing Templates If a hook template is missing, Twig will throw an error. Handle gracefully:
{% hooks 'hook_name' ignore_missing %}
Circular Dependencies
Avoid hooks that reference each other (e.g., hook_a includes hook_b, which includes hook_a).
Performance Each hook adds a Twig node compilation overhead. Benchmark heavily used hooks.
TWIG_DEBUG=1 in your .env to see hook-related errors and template paths.dump($this->twigHooks->getHooks()) to inspect registered hooks in a controller.HooksNode to add logic (e.g., validate hook names or modify rendering).HookAddedEvent).mybundle_product_header).@BundleName/ or :: syntax for absolute paths:
{% hooks 'hook_name' with {'template': '@MyBundle/hook/template.html.twig'} %}
README with examples and expected data.TwigHooks directly:
$twigHooks = new TwigHooks();
$twigHooks->addHook('test', 'test.html.twig');
$this->assertStringContainsString('Hook content', $twigHooks->renderHooks($twig, 'test'));
ThemeContext to pass theme-specific hooks dynamically.How can I help you explore Laravel packages today?