Skip to content

Latest commit

 

History

History
202 lines (147 loc) · 4.15 KB

templates.md

File metadata and controls

202 lines (147 loc) · 4.15 KB

Templates

A simple template engine separates logic from the presentation and provides methods for creating nested templates and escaping strings to protect against too common XSS vulnerabilities.

Template engine initialization:

$template = new App\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://bugs.php.net',
    // ...
]);

Page can be rendered in the controller:

echo $template->render('pages/how_to_report.php', [
    'mainHeading' => 'How to report a bug?',
]);

The templates/pages/how_to_report.php:

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

<?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>PHP Bug Tracking System :: <?= $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/report_bug.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) ?>