Skip to content

Support other template engines #9

Open
@jameswilson

Description

@jameswilson

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;
        }
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions