Download the PHP package nowo-tech/word-template-bundle without Composer
On this page you can find all versions of the php package nowo-tech/word-template-bundle. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download nowo-tech/word-template-bundle
More information about nowo-tech/word-template-bundle
Files in nowo-tech/word-template-bundle
Package word-template-bundle
Short Description Symfony bundle: fill .docx Word templates (PHPWord TemplateProcessor) from a context array — scalars, rich HTML, table rows, images.
License MIT
Homepage https://packagist.org/packages/nowo-tech/word-template-bundle
Informations about the package word-template-bundle
WordTemplateBundle
Found this useful? Install from Packagist (
composer require nowo-tech/word-template-bundle) and consider starring WordTemplateBundle on GitHub.
Symfony bundle that fills Microsoft Word .docx templates (PHPWord TemplateProcessor) using a PHP context array:
- Scalars (strings, numbers, booleans, null) →
setValueon placeholders such as${client_name}or${client.city}when you nest arrays (flattened to dot keys). - Expression conditionals (1.8, opt-in) →
${#if total > 1000}…${#endif}: the condition lives in the template and is evaluated against the context (operators,in,matches, Twig-like functions such asupper(),length(),date()), sandboxed — see Conditionals below. - Loops (1.8, opt-in) →
${#for line in lines}…${#endfor}repeats paragraphs or whole table rows per element, with${line.name},${loop.index}and conditions inside — see Loops below. ConditionalBlock→${#if block}…${#endif block}named regions (several sibling and nested blocks supported); show or remove from PHP. Markers split across Word runs are healed before apply. For named blocks you pass abool— see Conditionals by data type for how to derive it frombool,int,float,string,null, arrays, dates, enums, Doctrine relations and request/form data, the "else" and "one of N" patterns, and where markers may go in Word.TableRows→cloneRow+ per-cell#1,#2, … replacements for repeating table lines (several independent tables in one.docxvia distinct anchors; oneTableRowsper table row).HtmlContent→ rich fragments (paragraphs, bold/italic, tables inside HTML, etc.) via PHPWordHtml::addHtmlembedded as a complex block (lists<ul>/<ol>may require extra numbering setup in PHPWord; prefer plain paragraphs or combine with HtmlToWordBundle for full HTML pipelines).ImageSource→setImageValuewith optional width/height.listVariables()→ unique paint placeholder names (includes fields inside conditionals; omits#if/#endifmarkers).listConditionalBlocks()→ unique conditional block names (e.g.annexfrom${#if annex}).listConditionalExpressions()/lintConditionalExpressions()→ list and validate the expression conditionals of a template before merging (e.g. on upload). This bundle does not execute Word VBA macros; “macros” here means template placeholders in the.docxcompatible with PHPWord. Under FrankenPHP (especially worker mode),process()is bounded by a configurabletimeout(default 180s, cooperative deadline +set_time_limit) so a long merge cannot pin a worker forever. See docs/FRANKENPHP-WORKER-AUDIT.md.
Conditionals
Two ways to keep or remove part of a document — both in the same template if you like:
| Named block (decided in PHP) | Expression (decided in the template, 1.8 opt-in) | |
|---|---|---|
| In Word | ${#if annex} … ${#endif annex} |
${#if total > 1000} … ${#endif} |
| In PHP | 'annex' => new ConditionalBlock('annex', $hasAnnex) |
'total' => $order->total() |
| Enable | always on | nowo_word_template.conditional_expressions.enabled: true |
| Branches | — (two blocks with opposite decisions) | ${#elseif total > 100} … ${#else} … ${#endif} (1.9) |
In Word (each marker in its own paragraph):
In PHP:
Result: Invoice F-2026-001 · Orders above 1,000 EUR ship for free within Spain. · Please pay before 2026-11-15.
Expressions use Symfony ExpressionLanguage syntax with no access to PHP functions, constants or objects — only the context values and a whitelist of Twig-like functions (lower, upper, trim, length, replace, round, number_format, join, default, is_defined, now, date, …; your own via a tagged provider). Errors (typos, unknown variables) throw ConditionalExpressionException by default. Word's typographic quotes are handled. Full reference: USAGE — Conditionals by data type for named blocks.
Rendered by the demo (make docx-previews, LibreOffice) — template in Word → generated document:
| Expression true / false | Nested blocks | "Else" pair |
|---|---|---|
| One of N | Table only when there are rows | Functions |
| Named block (PHP) | Dates | |
Loops
(1.8, opt-in: nowo_word_template.loops.enabled: true) — repeat paragraphs, or whole table rows when the markers sit in rows of their own:
In Word (each | line is a table row):
In PHP:
Result: one row per line (1 | Anchor bolts | 40, 2 | Brackets | 25.5), then Total | | 65.5.
Twig-like loop.index, index0, revindex, first, last, length, parent; ${#for key, value in map}; ${#if …} and nested loops inside the body see the loop variables; iteration caps protect workers. Full reference: USAGE — Loops.
| Invoice rows + conditional row | Nested loops | Loop variables |
|---|---|---|
Demo pages (demo/symfony8):
| Template form | Conditionals (named + expression decisions) | Expression examples (Word / PHP / result) | Loops |
|---|---|---|---|
This bundle is FrankenPHP worker mode friendly.
It stays safe in kernel-not-reset workers (scenario B): see docs/FRANKENPHP-WORKER-AUDIT.md.
Versioning
Quick start
Register Nowo\WordTemplateBundle\WordTemplateBundle if needed, then wire your templates and inject WordTemplateProcessorInterface:
Requirements
- PHP 8.2+
- Symfony 7.4+ / 8.x (as in
composer.json) - Extensions:
dom,json,libxml,zip
Development
Demos (FrankenPHP)
Demos run with FrankenPHP (Caddy + PHP in Docker). docker-compose defaults to APP_ENV=dev, so the entrypoint uses Caddyfile.dev (no PHP worker), and Twig/PHP changes are visible on refresh. Worker mode applies to a production-style setup — see docs/DEMO-FRANKENPHP.md.
From the repository root:
Or from demo/: make up (see demo/README.md).
The demo has four pages (the fourth, /loops, shows invoice-style row loops, loop variables, nested loops, maps and empty lists the same way): / fills a template discovered with listVariables() (scalars, HtmlContent, TableRows, nested conditionals, images); /conditionals shows one form field per PHP type, the ConditionalBlock decision each one produces and the expression conditionals of the same template, and downloads the merged .docx; /conditionals/examples shows each expression case as Word text, PHP context and result, with the template and the generated .docx to download. Playwright: make -C demo/symfony8 test-e2e, demo-screenshots, docx-previews.
Documentation
- Installation
- Configuration
- Usage
- Conditionals by data type — bool/int/float/string/null/array/date/enum/Doctrine/request examples, pitfalls, missing blocks, marker placement
- functions reference, nesting, errors, security
- Loops —
${#for line in lines}…${#endfor}: paragraphs, table rows, loop variables, nesting, limits
- Contributing
- Code of Conduct
- Changelog
- Upgrading
- Release
- Security
- Engram
- Spec-driven development
- GitHub Spec Kit
Additional documentation
- GitHub Actions CI requirements
- PSR evaluation (REQ-CS-007)
demo/README.md)- FrankenPHP worker audit (kernel not reset)
Tests and coverage
Measured on 2026-10-29 with composer coverage-check (PHP 8.2 + PCOV, same command as the CI Tests & QA job):
| Language | Line coverage | Gate | Command |
|---|---|---|---|
| PHP | 100% (lines of src/, Clover coverage/coverage.xml) |
100% — composer coverage-check fails below it (CI, make release-check) |
make coverage-check |
| TS/JS | N/A (no TypeScript/JavaScript code) | — | — |
| Python | N/A (no Python code) | — | — |
- PHPUnit —
composer test:tests/Unitandtests/Integration(minimal kernel intests/Fixtures/AppKernel.php; real.docxtemplates built with PHPWord at runtime). - Measured scope — all of
src/(phpunit.xml.dist<source>); no exclusion and no@codeCoverageIgnore. - Reports —
composer test-coverage/coverage-checkwritecoverage/coverage.xmland the text summary intocoverage/(thecoverage-dataDocker volume).
License
MIT License.
All versions of word-template-bundle with dependencies
ext-dom Version *
ext-json Version *
ext-libxml Version *
ext-zip Version *
phpoffice/phpword Version ^1.4
psr/log Version ^1.1 || ^2.0 || ^3.0
symfony/cache Version ^7.4 || ^8.0
symfony/clock Version ^7.4 || ^8.0
symfony/config Version ^7.4 || ^8.0
symfony/dependency-injection Version ^7.4 || ^8.0
symfony/expression-language Version ^7.4 || ^8.0
symfony/http-kernel Version ^7.4 || ^8.0
symfony/yaml Version ^7.4 || ^8.0