# symfony/templating: the loader, the name parser and a plain PHP engine

> The Templating component is the part of Symfony that many projects meet only as a dependency, and it does two separable things. It provides the infrastructure for loading template files and optionally monitoring them for changes, and it ships one concrete engine, a plain PHP implementation with escaping helpers and a way of separating a template into blocks and layouts. It is MIT licensed and lives on the 6.4 branch.

**symfony/templating** — Provides all the tools needed to build any kind of template system

- Repository: https://github.com/symfony/templating
- Website: https://symfony.com/templating
- Stars: 1,016 · Forks: 18
- Language: PHP
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/symfony-templating

## Two separable halves in one component

The README describes the component as providing all the tools needed to build any kind of template system, and then breaks that into two things. The first is infrastructure to load template files and optionally monitor them for changes. The second is a concrete template engine implementation using PHP, with additional tools for escaping and for separating templates into blocks and layouts. That split is the design decision that makes the component useful beyond Symfony. A project that wants its own template language can take the loader, the name parsing and the reference objects, and implement the engine side itself, and a project that simply wants to render PHP templates with a parser can use the shipped `PhpEngine` and ignore the fact that it is replaceable. The presence of separate interfaces in the tree, an `EngineInterface`, a `StreamingEngineInterface` and a `DelegatingEngine`, says the same thing in code: the engine is one participant in a contract, not the centre of the component.

## Loaders, name parsing and the reference object

The loader layer is where the file system meets the template names, and the tree separates them into a `Loader/` directory and a pair of name parsing classes. The quick start wires a `FilesystemLoader` over a directory with a placeholder in the path, `__DIR__.'/views/%name%'`, and pairs it with a `TemplateNameParser`. The parser's job is to turn the name you ask for into a `TemplateReference`, and the interfaces `TemplateNameParserInterface` and `TemplateReferenceInterface` sit alongside the concrete classes so a project can substitute its own naming rules. The placeholder in the loader path is the practical part. A loader rooted at `views/%name%` means the template name selects the file inside a fixed structure, which is the mechanism that lets a template name carry a path without letting it escape the configured root, and it is why the parser and the loader are separate collaborators rather than one class.

## The concrete engine, and the helper that adds slots

The engine implementation is `PhpEngine`, and the first example shows the whole assembly in three objects, a filesystem loader, a name parser and the engine, followed by a call to set a helper on it and a render. The helper in that example is `SlotsHelper`, which is the piece that supports separating a template into blocks and layouts, and the `Helper/` directory in the repository is where that family of helpers lives. The escaping story is visible in the example template itself, where the variable is printed through `$view->escape($firstname)` rather than directly, and that single method call is the difference between a template system that protects you from injected markup and one that does not. The other observable detail is that the example passes an array of variables into `render`, so the data reaches the template as a plain PHP variable, and the template refers to it by name. Nothing about that is unusual, and that is the point of the component: the abstractions it adds sit on top of PHP rather than replacing it.

## Three interfaces and what they separate

The top level of the repository lists the abstractions, and reading them tells you how the component decomposes. `EngineInterface` is the basic contract, something that can render a template name with a set of variables and return output. `StreamingEngineInterface` is the variant for engines that can emit output incrementally rather than building the whole string first, which matters when a template streams a large response. `DelegatingEngine` is the decorator that forwards to another engine, and it is the natural place to add behaviour such as instrumentation or caching without touching the engine itself. `TemplateReference` and `TemplateReferenceInterface` are the value objects that carry a resolved template identity, and `TemplateNameParserInterface` is the seam that produces them. A `Storage/` directory sits alongside the loaders, which suggests the component is prepared for a case where the template bytes come from somewhere other than the local file system, and the README's mention of monitoring templates for changes is the counterpart to that, since a file based loader is what you monitor.

## The first render, end to end

The getting started section is a composer require and a short script, and the script is the whole API in miniature.

```php
use Symfony\Component\Templating\Loader\FilesystemLoader;
use Symfony\Component\Templating\PhpEngine;
use Symfony\Component\Templating\Helper\SlotsHelper;
use Symfony\Component\Templating\TemplateNameParser;

$filesystemLoader = new FilesystemLoader(__DIR__.'/views/%name%');

$templating = new PhpEngine(new TemplateNameParser(), $filesystemLoader);
$templating->set(new SlotsHelper());

echo $templating->render('hello.php', ['firstname' => 'Fabien']);
```

Two implementation choices are worth noticing. The engine takes the parser and the loader as constructor arguments rather than building them, so a project can swap either without subclassing the engine. And the helper is installed through a `set` call on the engine, so the engine does not depend on the helper and the helper does not depend on the engine, which is what lets the same engine serve a project that wants slots and one that does not. The template that receives the data then escapes it at the point of output, as the example template does with `$view->escape($firstname)`.

## Where this component sits, and what to check before you use it

The repository is a Symfony component rather than an application, so the usual questions about a project do not quite apply. It is tracked on the 6.4 branch, with the newest tags being v6.4.24 from 2025-07-31, v6.4.13 and the 5.4.45 maintenance line from October 2024, and the last push on the branch was on 2026-06-05. The component's own test suite lives in `Tests/` with a `phpunit.xml.dist`, and the `CHANGELOG.md` in the root is where behaviour changes within a patch line are recorded, which is the file to read if you are chasing a regression in a 6.4 release. Two practical points close this out. First, the change monitoring mentioned in the overview is a property of the loader, so if you want a template edit to show up without clearing a cache you need to turn that on, and in a development environment it is usually the difference between a good and an annoying editing loop. Second, because the component is infrastructure plus one engine, the question to ask when evaluating it is whether you want Symfony's loader and helpers with a different engine, or this engine, because the answer determines whether you need the component at all.

## Conclusion

Adopt symfony/templating if you are building a template system of your own on top of Symfony's component stack, or if you want the loader, the name parser and the escaping helpers without committing to a full framework. Do not reach for it expecting a batteries included rendering stack, because the concrete engine here is plain PHP templates rather than a component oriented one, and the component's own scope is infrastructure rather than a full templating language. Before you start, check the branch you are on, since this repository tracks the 6.4 line and the newest tag is v6.4.24 from 2025-07-31, and decide whether you need the change monitoring at all, because it is an opt-in behaviour of the loader rather than something you get by default. The licence is MIT, the homepage is symfony.com/templating, and the last push was on 2026-06-05.

## FAQ

### What does symfony/templating provide?

It provides the infrastructure to load template files and optionally monitor them for changes, plus a concrete template engine implementation using PHP with additional tools for escaping and for separating templates into blocks and layouts.

### How do I install the Symfony Templating component?

With `composer require symfony/templating`. The package is MIT licensed and its documentation lives at symfony.com/templating, with the API reference for the component and the getting started material on the project site.

### How do I escape a variable in a Symfony template?

Print it through the view's escape method, as the example template does with `<?= $view->escape($firstname) ?>`. The component's description lists escaping among the additional tools the concrete PHP engine provides on top of the loader infrastructure.

### Can I replace the template engine in symfony/templating?

Yes. The engine is constructed from a name parser and a loader rather than building them itself, and the repository defines an `EngineInterface`, a `StreamingEngineInterface` for engines that emit output incrementally, and a `DelegatingEngine` decorator, with `TemplateNameParserInterface` and `TemplateReferenceInterface` as the seams for naming.

## Sources

- [License: MIT](https://github.com/symfony/templating/blob/6.4/LICENSE)
- [Project website](https://symfony.com/templating)
- [README](https://github.com/symfony/templating/blob/6.4/README.md)
- [Releases](https://github.com/symfony/templating/releases)
- [symfony/templating on GitHub](https://github.com/symfony/templating)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/symfony-templating
