Codeskill

Learn to code, step by step

Twig or plain PHP templates – keeping HTML out of logic

Let’s compare plain PHP templates and Twig for keeping HTML out of your business logic. Mixed PHP and HTML in controllers gets messy fast.

Plain PHP templates

A template is a PHP file that mostly HTML, with short echo blocks. Pass data in as variables:

// Controller:
return view('notes/index', ['notes' => $notes, 'title' => 'My notes']);

// helpers/view.php:
function view(string $name, array $data = []): string
{
    extract($data, EXTR_SKIP);
    ob_start();
    require dirname(__DIR__) . '/templates/' . $name . '.php';
    return ob_get_clean();
}
<!-- templates/notes/index.php -->
&lt;h1&gt;&lt;?= htmlspecialchars($title, ENT_QUOTES, 'UTF-8') ?&gt;&lt;/h1&gt;
&lt;ul&gt;
  &lt;?php foreach ($notes as $note): ?&gt;
    &lt;li&gt;&lt;?= htmlspecialchars($note['title'], ENT_QUOTES, 'UTF-8') ?&gt;&lt;/li&gt;
  &lt;?php endforeach; ?&gt;
&lt;/ul&gt;

Layouts

Avoid copying header and footer on every page. Use a layout wrapper:

// templates/layout.php
&lt;!DOCTYPE html&gt;
&lt;html lang="en-GB"&gt;
&lt;head&gt;&lt;title&gt;&lt;?= htmlspecialchars($title ?? 'App') ?&gt;&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;
  &lt;?php include __DIR__ . '/partials/nav.php'; ?&gt;
  &lt;main&gt;&lt;?php include $contentTemplate; ?&gt;&lt;/main&gt;
&lt;/body&gt;
&lt;/html&gt;

Twig option

Twig auto-escapes output by default and has inheritance (extends, block). Install with Composer:

composer require twig/twig
$loader = new TwigLoaderFilesystemLoader(dirname(__DIR__) . '/templates');
$twig = new TwigEnvironment($loader, ['cache' => false]);

echo $twig->render('notes/index.twig', ['notes' => $notes]);
{# templates/notes/index.twig #}
{% extends 'layout.twig' %}
{% block title %}My notes{% endblock %}
{% block content %}
  &lt;ul&gt;
    {% for note in notes %}
      &lt;li&gt;{{ note.title }}&lt;/li&gt;
    {% endfor %}
  &lt;/ul&gt;
{% endblock %}

Which to pick

  • Plain PHP – zero dependencies, full control, you handle escaping
  • Twig – safer defaults, nicer inheritance, small learning curve

Either beats echoing HTML from a controller. Pick one, stay consistent, and always escape user data on output.

PreviousWorking with APIs from PHP (curl/HTTP clients)