/template-engine

Generic template engine written in PHP

Primary LanguagePHP

Template engine

Build Status

Generic template engine written in PHP. It separates logic from the presentation and provides methods for creating nested templates and escaping strings to protect against too common XSS vulnerabilities.

Installation

composer require petk/template-engine

Usage

Template engine initialization:

$template = new Petk\Template\Engine(__DIR__.'/../path/to/templates');

Site-wide configuration parameters can be assigned before rendering so they are available in all templates:

$template->assign([
    'siteUrl' => 'https://example.com',
    // ...
]);

Page can be rendered in the controller:

echo $template->render('pages/about_us.php', [
    'mainHeading' => 'A short introduction',
]);

The templates/pages/about_us.php:

<?php $this->extends('layout.php', ['title' => 'About us']) ?>

<?php $this->start('main_content') ?>
    <h1><?= $this->noHtml($mainHeading) ?></h1>

    <p><?= $siteUrl ?></p>
<?php $this->end('main_content') ?>

<?php $this->start('scripts') ?>
    <script src="/js/feature.js"></script>
<?php $this->end('scripts') ?>

The templates/layout.php:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <link rel="stylesheet" href="/css/style.css">
        <title>ACME :: <?= $title ?? '' ?></title>
    </head>
    <body>
        <?= $this->block('main_content') ?>

        <div><?= $siteUrl ?></div>

        <script src="/js/app.js"></script>
        <?= $this->block('scripts') ?>
    </body>
</html>

Including templates

To include a partial template snippet file:

<?php $this->include('forms/contact.php') ?>

which is equivalent to <?php include __DIR__.'/../forms/contact.php' ?>, except that the variable scope is not inherited by the template that included the file. To import variables into the included template snippet file:

<?php $this->include('forms/contact.php', ['formHeading' => 'value', 'foo' => 'bar']) ?>

Blocks

Blocks are main building elements that contain template snippets and can be included into the parent file(s).

Block is started with the $this->start('block_name') call and ends with $this->end('block_name'):

<?php $this->start('block_name') ?>
    <h1>Heading</h1>

    <p>...</p>
<?php $this->end('block_name') ?>

Appending blocks

Block content can be appended to existing blocks by the $this->append('block_name').

The templates/layout.php:

<html>
<head></head>
<body>
    <?= $this->block('content'); ?>

    <?= $this->block('scripts'); ?>
</body>
</html>

The templates/pages/index.php:

<?php $this->extends('layout.php'); ?>

<?php $this->start('scripts'); ?>
    <script src="/js/foo.js"></script>
<?php $this->end('scripts'); ?>

<?php $this->start('content') ?>
    <?php $this->include('forms/form.php') ?>
<?php $this->end('content') ?>

The templates/forms/form.php:

<form>
    <input type="text" name="title">
    <input type="submit" value="Submit">
</form>

<?php $this->append('scripts'); ?>
    <script src="/js/bar.js"></script>
<?php $this->end('scripts'); ?>

The final rendered page:

<html>
<head></head>
<body>
    <form>
        <input type="text" name="title">
        <input type="submit" value="Submit">
    </form>

    <script src="/js/foo.js"></script>
    <script src="/js/bar.js"></script>
</body>
</html>

Helpers

Registering additional template helpers can be useful when a custom function or class method needs to be called in the template.

Registering function

$template->register('formatDate', function (int $timestamp): string {
    return gmdate('Y-m-d H:i e', $timestamp - date('Z', $timestamp));
});

Registering object method

$template->register('doSomething', [$object, 'methodName']);

Using helpers in templates:

<p>Time: <?= $this->formatDate(time()) ?></p>
<div><?= $this->doSomething('arguments') ?></div>

Escaping

When protecting against XSS there are two built-in methods provided.

To replace all characters to their applicable HTML entities in the given string:

<?= $this->noHtml($var) ?>

To escape given string and still preserve certain characters as HTML:

<?= $this->e($var) ?>

License and contributing

Contributions are most welcome by forking the Git repository over GitHub and sending a pull request.