Views & Templates
Fast's view layer is refreshingly boring, and that is a feature. There is no template engine, no compilation step, and no new syntax to learn. Your templates are just PHP files, and you use plain PHP to loop, branch, and print.
Enabling views
Point Fast at a directory of templates with use_views(), then render them by name with the render() helper:
use_views(__DIR__ . '/views');
get('/', fn (): string => render('home', ['title' => 'Hi']));
The template itself is embedded PHP. The data array you pass to render() becomes local variables inside the template:
<!-- views/home.php -->
<h1><?= e($title) ?></h1>
render() returns the rendered HTML as a string, which your handler can return directly (strings become HTML responses) or embed inside a larger response.
Always escape output
You will notice e($title) in that example instead of a bare <?= $title ?>. The e() helper HTML-escapes its argument, and you should wrap every value that could contain user input in it. This is your primary defense against cross-site scripting.
<p>Welcome back, <?= e($user->name) ?>.</p>
<ul>
<?php foreach ($items as $item): ?>
<li><?= e($item) ?></li>
<?php endforeach ?>
</ul>
e() is an alias for escape(); use whichever you prefer. The rule of thumb is simple: if it came from outside your code, escape it on the way out.
Escaping is especially important with Fast's live fragments, where an out-of-band update can rewrite arbitrary parts of the page. Unescaped output there is not just a bug, it is a real injection risk. When in doubt,
e()it.
Organizing templates
Templates can live in subdirectories, and you reference them with a slash-separated name. A file at views/live/results.php is rendered as render('live/results'). Templates can also render other templates, which is how you build partials and layouts:
<!-- views/layout.php -->
<!DOCTYPE html>
<html>
<head><title><?= e($title) ?></title></head>
<body>
<?= $content ?>
</body>
</html>
get('/', function (): string {
$content = render('home', ['name' => 'World']);
return render('layout', ['title' => 'Home', 'content' => $content]);
});
Because it is all just PHP, you are never fighting the tool. Any pattern you would use in plain PHP templating works here, including helper functions you define yourself.
Static assets like CSS and images are handled separately, which we cover next in Static Files.