Installation
composer require codemade-xyz/php-liquid-bundle
Add the bundle to config/bundles.php:
return [
// ...
CodeMade\LiquidBundle\LiquidBundle::class => ['all' => true],
];
First Use Case
Create a Liquid template at templates/liquid/example.liquid:
{% for item in items %}
<p>{{ item.name }} - {{ item.price | price }}</p>
{% endfor %}
Render it in a Symfony controller:
use CodeMade\LiquidBundle\Liquid\Engine;
public function index(Engine $engine)
{
$template = $engine->getTemplate('example.liquid');
$output = $template->render([
'items' => [
['name' => 'Product 1', 'price' => 19.99],
['name' => 'Product 2', 'price' => 29.99],
],
]);
return new Response($output);
}
Where to Look First
price, prettyprint, and paragraph in src/CodeMade/LiquidBundle/Filter/.config/packages/liquid.yaml for cache and path settings.Dynamic Template Rendering Use Liquid for dynamic content generation (e.g., emails, notifications, or CMS-driven pages):
$template = $engine->getTemplate('emails/welcome.liquid');
$template->render(['user' => $user]);
Reusable Components
Create modular Liquid templates (e.g., _header.liquid, _footer.liquid) and include them:
{% render 'partials/header' %}
<main>{{ content }}</main>
{% render 'partials/footer' %}
Custom Filters Extend Liquid with custom filters (e.g., for formatting dates or truncating text):
# config/packages/liquid.yaml
liquid:
filters:
- App\Filter\CustomFilter
// src/Filter/CustomFilter.php
namespace App\Filter;
use CodeMade\LiquidBundle\Filter\FilterInterface;
class CustomFilter implements FilterInterface {
public function filter($input) {
return strtoupper($input);
}
}
Caching Leverage Symfony’s cache for performance:
liquid:
cache: '%kernel.cache_dir%/liquid'
Symfony Twig Integration Use Liquid alongside Twig for hybrid templating (e.g., Liquid for dynamic content, Twig for layouts):
{# templates/base.html.twig #}
<div id="dynamic-content">
{{ include('liquid/_dynamic.liquid', {'data': data})|raw }}
</div>
API-Driven Templates Fetch Liquid templates dynamically from a database or API:
$templateContent = $db->fetchTemplate($templateId);
$engine->getTemplateFromString($templateContent)->render($data);
Testing
Mock the Engine service in PHPUnit:
$engine = $this->createMock(Engine::class);
$engine->method('getTemplate')->willReturn($templateMock);
Deprecated Bundle
Cache Invalidation
php bin/console cache:clear
liquid.yaml during development:
liquid:
cache: null
Filter Conflicts
FilterInterface; otherwise, they won’t register.price) to avoid breaking expected behavior.Security
|escape filter for user-generated content:
{{ unsafeInput | escape }}
Namespace Collisions
namespace App\Liquid\Tag;
Template Errors
config/packages/dev/liquid.yaml:
liquid:
debug: true
var/log/dev.log).Missing Templates
default_path in liquid.yaml points to the correct directory:
liquid:
default_path: '%kernel.project_dir%/templates/liquid'
Filter Issues
autoload-dev may be needed for custom filters).Performance
cache to a persistent directory.Extending Liquid
CodeMade\LiquidBundle\Tag\TagInterface:
class MyTag implements TagInterface {
public function parse(Parser $parser) { ... }
public function render(Engine $engine, array $params) { ... }
}
liquid.yaml:
liquid:
tags:
- App\Liquid\Tag\MyTag
IDE Support
Fallbacks
{% for product in products | default([]) %}
Testing Edge Cases
null values, and nested objects to ensure robustness:
{{ user.address.city | default('N/A') }}
How can I help you explore Laravel packages today?