tereta / theme
Template engine for PHP 8.2+: a fluent view builder that renders .phtml templates with meta and data, and resolves nested includes relative to the theme root.
Requires
- php: >=8.2
- psr/container: ^2.0
Requires (Dev)
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0
- squizlabs/php_codesniffer: ^3.13
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
๐ English | ะ ัััะบะธะน | ะฃะบัะฐัะฝััะบะฐ
Template engine for PHP.
It renders .phtml templates from a theme folder and lets one template include another.
Requirements
PHP 8.2+, psr/container ^2.0.
Installation
composer require tereta/theme
Quick start
A theme is a folder with .phtml templates:
themes/base/
โโโ page/
โ โโโ product.phtml
โโโ blocks/
โโโ footer.phtml
Render a template by its name inside the theme, without .phtml:
use Tereta\Theme\View;
$view = new View('/path/to/themes/base');
$html = $view->builder()
->setTemplate('page/product')
->setMeta(['lang' => 'en'])
->setData(['title' => 'Hello'])
->render();
Inside a template
Each value from setData() becomes a variable with the same name.
Meta values are available in $meta.
Print every value through $escape:
<!-- page/product.phtml -->
<html lang="<?= $escape($meta['lang']) ?>">
<h1><?= $escape($title) ?></h1>
All data is also available as one array in $data.
Safe output
The template engine does not escape values by itself: <?= $title ?> prints the value exactly as it is.
So print every value with $escape, even if it looks safe now - a title or a name can come from a user or from the database later.
$escape turns the special HTML characters, quotes too, into safe text, so it works both in text and in attribute values:
<h1><?= $escape($title) ?></h1>
<input name="title" value="<?= $escape($title) ?>">
If $title is <b>Tom & Jerry</b>, the page shows exactly this text and not bold text.
Print a value without $escape only when it is HTML that you have made yourself and trust, for example the result of another render().
Mark such a place with a comment, so it is clear that it is not a mistake:
<?= $content /* trusted HTML from render() */ ?>
$escape does not check links: an address like javascript:... still works after escaping.
Check the addresses of links that come from users before you print them.
$escape accepts a string, a number or null.
Include one template into another
Use $include with a template name from the theme folder:
<?php $include('blocks/footer') ?>
The name is always counted from the theme folder, not from the current template.
A template can not be included from outside the theme folder, for example with ../.
The included template gets the same $meta and data.
The second parameter passes an extra value, it is available in $attribute:
<!-- page/product.phtml -->
<?php $include('blocks/menu', $meta['menu']) ?>
<!-- blocks/menu.phtml -->
<?php foreach ($attribute as $item) : ?>
<a href="<?= $escape($item['url']) ?>"><?= $escape($item['label']) ?></a>
<?php endforeach ?>
The names meta, data, include, escape, attribute, template and variables are reserved.
Data keys with these names do not become variables, but they are still in $data.
Theme settings
Tereta\Theme\Context\Config stores theme settings, for example the themes folder and the current theme:
use Tereta\Theme\Context\Config;
$config = (new Config())
->set('path', '/path/to/themes')
->set('theme', 'base');
$view = new View($config->get('path') . '/' . $config->get('theme'));
has() checks whether a setting exists.
Errors
Tereta\Theme\Exceptions\Template- the template or the theme folder is not found, or the template is outside the theme folder.Tereta\Theme\Exceptions\NotFound- the setting is not found inConfig.