lliure/twig-container
Composer 安装命令:
composer require lliure/twig-container
包简介
Twig extension for container-based template composition with additive content injection
README 文档
README
Vue-like slots for Twig. Container-based template composition with additive content injection.
Perfect for injecting scripts, styles, and components from child templates into parent layouts.
Why This Library?
Twig's native {% block %} is substitutive - child blocks replace parent blocks. But sometimes you need additive composition:
{# ❌ Problem: Each component overwrites the scripts block #}
{% block scripts %}
<script src="datepicker.js"></script>
{% endblock %}
{# ✅ Solution: Components ADD to the container #}
{% inject 'scripts' %}
<script src="datepicker.js"></script>
{% endinject %}
Features
| Feature | Description |
|---|---|
| Containers | Named areas that accumulate content |
| Inject | Add content from anywhere (before or after the container) |
| Unique | Prevent duplicate injections (CSS/JS) |
| Package | Reusable components with isolated context |
| content() | Mix original content with injections |
Comparison with Alternatives
| Feature | twig-stack | lliure/twig-container |
|---|---|---|
| Push/Inject | ✓ | ✓ |
| Prevent duplicates | pushonce | unique with auto or manual ID |
| Mix original + injected | ✗ | ✓ {{ content() }} |
| Reusable components | ✗ | ✓ {% package %} |
| Dynamic paths | ✗ | ✓ {% package path ~ '.twig' %} |
Installation
composer require lliure/twig-container
Quick Start
use TwigContainer\Container;
use TwigContainer\ContainerRuntime;
// Add extension
$twig->addExtension(new Container());
// Add runtime loader
$twig->addRuntimeLoader(new class implements \Twig\RuntimeLoader\RuntimeLoaderInterface {
private ?ContainerRuntime $runtime = null;
public function load(string $class): ?object {
if ($class === ContainerRuntime::class) {
return $this->runtime ??= new ContainerRuntime();
}
return null;
}
});
// Render with post-processing
$output = $twig->render('template.twig');
$runtime = $twig->getRuntime(ContainerRuntime::class);
echo $runtime->processPlaceholders($output);
Usage
Container
Define a named area:
{% container 'scripts' %}
<script src="base.js"></script>
{{ content() }}
{% endcontainer %}
{{ content() }}marks where injections appear- Without
content(): injections replace original content - Without injections: shows original content
Inject
Add content to a container:
{% inject 'scripts' %}
<script src="page.js"></script>
{% endinject %}
Works before or after the container (placeholder magic).
Unique Inject
Prevent duplicates (great for CSS/JS libraries):
{# Auto-unique based on file:line #}
{% inject 'styles' unique %}
<link rel="stylesheet" href="datepicker.css">
{% endinject %}
{# Manual ID for cross-file deduplication #}
{% inject 'styles' unique 'datepicker-css' %}
<link rel="stylesheet" href="datepicker.css">
{% endinject %}
Package
Include reusable components with isolated context:
{% package 'components/datepicker.twig' with {name: 'birthday', format: 'd/m/Y'} %}
Supports dynamic paths:
{% for field in fields %}
{% package 'components/' ~ field.type ~ '.twig' with field.config %}
{% endfor %}
Real-World Example
The Problem
You have a datepicker component used multiple times. You need:
- CSS loaded once
- JS initialization for each instance
- Everything in the right place (head/footer)
The Solution
components/datepicker.twig:
<input type="text" name="{{ name }}" class="datepicker" data-format="{{ format }}">
{# CSS - loads once per page #}
{% inject 'styles' unique 'datepicker' %}
<link rel="stylesheet" href="datepicker.css">
{% endinject %}
{# JS - one per instance #}
{% inject 'scripts' %}
<script>initDatepicker('{{ name }}', '{{ format }}');</script>
{% endinject %}
layout.twig:
<!DOCTYPE html>
<html>
<head>
{% container 'styles' %}{{ content() }}{% endcontainer %}
</head>
<body>
{% block content %}{% endblock %}
{% container 'scripts' %}
<script src="app.js"></script>
{{ content() }}
{% endcontainer %}
</body>
</html>
form.twig:
{% extends 'layout.twig' %}
{% block content %}
<form>
{% package 'components/datepicker.twig' with {name: 'start', format: 'd/m/Y'} %}
{% package 'components/datepicker.twig' with {name: 'end', format: 'd/m/Y'} %}
</form>
{% endblock %}
Output:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="datepicker.css">
</head>
<body>
<form>
<input type="text" name="start" class="datepicker" data-format="d/m/Y">
<input type="text" name="end" class="datepicker" data-format="d/m/Y">
</form>
<script src="app.js"></script>
<script>initDatepicker('start', 'd/m/Y');</script>
<script>initDatepicker('end', 'd/m/Y');</script>
</body>
</html>
CSS loads once, scripts load per instance.
Running Tests
php tests/run.php # Visual output
php tests/run.php --validate # Exit code for CI
License
MIT - see LICENSE
Contributing
Issues and PRs welcome at Bitbucket.
lliure/twig-container 适用场景与选型建议
lliure/twig-container 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 0 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 03 月 23 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「container」 「package」 「twig」 「template」 「composition」 「inject」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 lliure/twig-container 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 lliure/twig-container 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 lliure/twig-container 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Shoot aims to make providing data to your templates more manageable
This Symfony bundle integrates PhpSpreadsheet into Symfony using Twig.
A Twig extension to insert css as inline styles with a tag
Caching and compression for Twig assets (JavaScript and CSS).
A fast and intuitive dependency injection container.
Twig extensions for Tracy Debugger
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 33
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-03-23