Open
Description
Thanks for your work on this project. I'm planning on using it to put together a simple HTMX example app.
It would be interesting to add in optional support for the Twig template engine. Regardless of anyone's stance on Symfony, it is a fantastic template language and doesn't even require the entire Symfony package ecosystem to use it standalone.
Something like this would be cool:
composer require twig/twig
$app = new \PhpExpress\Application();
$app->set('views', 'path/to/views');
$app->set('twig_options', [
'cache' => 'path/to/twig_cache',
// Uncomment for local development only.
// 'debug' => true,
// 'auto_reload' => true,
]);
$app->get('/', function ($req, $res) {
$res->render('base', [
'title' => 'Home page',
'message' => 'This is the home page',
]);
});
$app->get('about', function ($req, $res) {
$res->render('about', [
'title' => 'About page',
'message' => 'This is the about page',
]);
});
Then in template folder we have:
views/base.twig:
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
{% block header %}
<h1>{{ title }}</h1>
{% endblock %}
{% block content %}
<div>{{ content }}</div>
<a href="/about">About</a>
{% endblock %}
</body>
</html>
views/about.html.twig:
{% extends "base.twig" %}
{% block content %}
<div>{{ content }}</div>
<a href="/">Home</a>
{% endblock %}
In Application::render()
we can hand down local variables into the Twig template if a matching view filename with extension .twig
is found.
Then we can check if Twig FilesystemLoader class exists. The following is working for me:
public function render(string $view, array $locals=null): void
{
if ($locals)
{
extract($locals);
}
$views_dir = $this->set("views");
$layout = sprintf("%s/%s.php", $views_dir, $view);
$_twig = sprintf("%s/%s.twig", $views_dir, $view);
$_template = sprintf("%s/%s.php", $views_dir, $this->set("template"));
if (is_file($_template))
{
include $_template;
} elseif (is_file($_twig)) {
if (!class_exists('\Twig\Loader\FilesystemLoader')) {
$filepath = realpath($_twig);
throw new \Exception("Please `composer require twig/twig` to proceed. A Twig template '{$filepath}' was found but the Twig template engine could not be loaded");
}
$loader = new \Twig\Loader\FilesystemLoader($views_dir);
$twig = new \Twig\Environment($loader, $this->set("twig_options"));
echo $twig->render(sprintf('%s.twig', $view), $locals);
} else {
include $layout;
}
}