Installation
composer require crunch/ssi-bundle
Add to config/bundles.php:
return [
// ...
Crunch\SsiBundle\CrunchSsiBundle::class => ['all' => true],
];
Basic Configuration
Edit config/packages/crunch_ssi.yaml:
crunch_ssi:
enabled: true
cache_dir: '%kernel.cache_dir%/ssi'
default_fragment_ttl: 3600 # 1 hour in seconds
First Use Case
Create a fragment template at templates/partials/_header.html.twig:
{# templates/partials/_header.html.twig #}
<header>
<h1>Welcome, {{ app.user.name }}</h1>
</header>
Render it in a layout:
{# templates/base.html.twig #}
{% ssi include '_header' %}
{% ssi include '_sidebar' with {'items': sidebarItems} %}
{% ssi include '_product_card' with {
product: product,
price: product.price - product.discount
} %}
Twig Extensions: Extend Twig with custom logic:
// src/Twig/AppExtension.php
class AppExtension extends \Twig\Extension\AbstractExtension
{
public function getFunctions()
{
return [
new \Twig\TwigFunction('get_ssi_cache_key', [$this, 'getCacheKey']),
];
}
public function getCacheKey($fragmentName, $params)
{
return \Crunch\SsiBundle\SsiRenderer::generateCacheKey($fragmentName, $params);
}
}
Event Listeners: Hook into fragment rendering lifecycle:
// src/EventListener/SsiListener.php
class SsiListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
SsiEvents::PRE_RENDER => 'onPreRender',
];
}
public function onPreRender(PreRenderEvent $event)
{
$fragment = $event->getFragment();
if ($fragment->getName() === 'analytics') {
$event->setContent('<!-- Analytics snippet -->');
}
}
}
$this->get('crunch_ssi.renderer')->invalidateFragment('header');
if with SSI:
{% if app.user.isAdmin %}
{% ssi include '_admin_tools' %}
{% endif %}
cache_dir is writable:
chmod -R 775 %kernel.cache_dir%/ssi
crunch_ssi:
enabled: true
cache_dir: null # Disables caching
crunch_ssi:
debug: true
Check logs for rendered fragments and cache hits/misses.Crunch\SsiBundle\Renderer\RendererInterface for non-Twig templates (e.g., PHP).SsiEvents::PRE_RENDER and SsiEvents::POST_RENDER to modify fragment content dynamically.crunch_ssi:
template_paths:
- '@App/partials'
- '@VendorBundle/partials'
{% ssi include '_header_v2' %}
{% ssi include '_optional_feature' ignore_missing=true %}
$fragmentName = preg_replace('/[^a-zA-Z0-9_]/', '', $fragmentName);
How can I help you explore Laravel packages today?