A template abstraction prototype for PHP template engines

Overview

PHP Templating Logo with a Rooster on it

Schranz Templating

A template abstraction prototype for PHP template engines.


This project should help to find a way for a general Template Render Interface.

Discussion in the PHP-FIG:

TODO

Usage for Library Authors

If you create a library, framework or whatever you should just require the template renderer in the require section of your composer.json:

composer require schranz-templating/template-renderer

Usage for Projects

Projects depending on libraries which where build on top of the schranz-templating/template-render abstract should require the renderer package and a bridge to the template engine they want to use:

composer require schranz-templating/aura-view-bridge
composer require schranz-templating/blade-bridge
composer require schranz-templating/handlebars-bridge
composer require schranz-templating/laminas-view-bridge
composer require schranz-templating/latte-bridge
composer require schranz-templating/mezzio-bridge
composer require schranz-templating/mustache-bridge
composer require schranz-templating/plates-bridge
composer require schranz-templating/qiq-bridge
composer require schranz-templating/smarty-bridge
composer require schranz-templating/spiral-view-bridge
composer require schranz-templating/twig-bridge
composer require schranz-templating/yii-view-bridge

Why Bridges?

As it would be too much work to create forks of every template engines to implement the interface for prototyping it is easier to use the Bridge Design Pattern to bridge from the TemplateRendererInterface to underlying template engines.

Usage for Symfony Projects

To use the integration in the Symfony the following packages are currently provided, which will register the bridge service and integration of the selected template engine:

composer require schranz-templating/symfony-blade-integration
composer require schranz-templating/symfony-handlebars-integration
composer require schranz-templating/symfony-latte-integration
composer require schranz-templating/symfony-mustache-integration
composer require schranz-templating/symfony-plates-integration
composer require schranz-templating/symfony-smarty-integration
composer require schranz-templating/symfony-twig-integration

Analysis

In the following table we will ist all yet found interesting template engines and view renderers. What kind of version they currently are and what PHP Version they are supporting. Also what kind of features are supported by them.

Engine Version PHP Version Inheritance Subviews Namespaces Functions Filters Exist Partial Streaming String Implemented
Twig 3.4.1 >=7.2.5 [x] [x] @ [x] [x] [x] [x] [x] [x] [x]
Smarty 4.1.1 ^7.1 ^8.0 [x] ? [x] ? ? ? [x] [x]
Latte 3.0.0 >=8.0 <8.2 [x] ? [x] ? ? ? [x] [x]
Blade 9.15.0 ^8.1 [x] [x] :: ? ? ? ? ? [x] [x]
Spiral View 2.13.1 >=7.4 [x] ? ? ? ? ? ? ? [x]
Mezzio 3.10.0 ~7.4.0 ~8.0.0 ~8.1.0 [x] [x] @ ? ? ? ? [x] [x]
Plates 3.4.0 ^7.0 ^8.0 [x] [x] :: [x] ? ? [x] [x]
Laminas View 2.20.0 ^7.4 ~8.0.0 ~8.1.0 [x] [x] ? ? ? ? ? ? [x] [x]
Yii View 5.0.0 ^7.4 ^8.0 [x] [x] [x] @ ? ? ? ? ? [x] [x]
Fluid 2.7.1 >=5.5.0 ? ? ? ? ? ? ? ? [x] [ ]
Contao 4.13.4 ^7.4 ^8.0 ? ? ? ? ? ? ? ? [x] [ ]
Mustache 2.14.1 >=5.2.4 ? ? ? ? ? ? ? ? [x] [x]
Handlebars 2.3.0 >=5.4.0 ? ? ? ? ? ? ? ? [x] [x]
Qiq 1.0.2 ^8.0 ? ? ? ? ? ? ? ? [x] [x]
Aura View 2.4.0 >=5.4.0 ? ? ? ? ? ? ? ? [x] [x]

Feature Support

In the table above it is listed which features are supported by different template engines. Beneath a more detail description about the requirement to fulfill it is given.

Inheritance

With support for template inheritance it means that a rendered template can inherit from a parent template and overwrite parts in the template language itself. This feature is not fulfilled for template engines which only allow to give subviews into a parent view or other way around.

E.g.: This is achieved in twig via extends and blocks. In blade via extends and sections keywords. In latte via layout and blocks keywords. Laminas view via the layout helper.

Subviews

This is the opposite way of creating layout and base template. Why it is possible via all engines to call several render calls and put template together. This is only fulfilled for template engines explicit working with a view, layout system and support given view with subviews them in the renderer call.

E.g.: In laminas view this is possible via the setLayout before calling the rendering of the template.

This is not fulfilled by twig, blade or latte as they support layout and inheritance only on template level not on render caller level.

Namespaces

The template engine allow to render specific template from different directories via namepaces. Also how a namespace is reference should be listed.

E.g. This is achieved in twig via the @Namespace/ and in Blade and Latte via namespace:: template names.

Functions

The template engine allows to define custom functions which can be called via the that name in the template.

E.g.: This is achieved in twig via twig extension and twig functions.

Exist

The template engine allows to check if a template with a specific name does exist or not.

E.g.: This is achieved in twig via the getLoader()->exist method.

Filter

The template engine allows to define custom filters which can be called via the that name on a specific variable in the template.

E.g.: This is achieved in twig via twig extension, twig filters and the filter | operator.

Partial

The template engine allows to render only a subpart of a template.

E.g. This is achieved in twig via loading the template and use the templates renderBlock method.

Streaming

Supports to stream the template directly to the output and not have the need to keep al in a string variable.

E.g. This is achieved in twig via the display method.

String

Supports to stream the template directly to the output and not have the need to keep al in a string variable.

E.g. This is achieved in twig via the display method.

Implemented

A bridge was already implemented for this engine and so a common interface for this type of engine would be possible.

Comments
  • Spiral framework integration

    Spiral framework integration

    Hi @alexander-schranz

    I've tried to refactor some of Bootloaders for Spiral Framework. I tried to show you how it could be if I did it.

    First of all, I don't understand the reason of using string nameslike 'schranz_templating.renderer.smarty' for container aliases. Why don't you use class names or interfaces?

    $container->bindSingleton('schranz_templating.renderer.smarty', function (Container $container) {
          return new SmartyRenderer($container->get('smarty'));
    });
    

    When you bind closures into container you can request dependencies as function arguments. You don't need request container and then get dependencies from them.

    $binder->bindSingleton(
        ViewFinderInterface::class,
        static function (BladeConfig $config, Filesystem $filesystem): ViewFinderInterface {
            return new FileViewFinder(
                $filesystem,
                $config->getPaths()
            );
        }
    );
    

    Spiral framework Bootloader can automatically load depended bootloaders before loading current.

    final class SpiralViewBootloader extends Bootloader
    {
        protected const DEPENDENCIES = [
            \Spiral\Views\Bootloader\ViewsBootloader::class
        ];
    
    
    Engine: Blade Engine: Twig Framework: Spiral 
    opened by butschster 3
  • Spiral: Revalidate the SpiralView Adapter

    Spiral: Revalidate the SpiralView Adapter

    Currently the SpiralView Adapter requires a EngineInterface, this we are currently getting directly from the ViewManager here:

    https://github.com/schranz-templating/templating/blob/5e8d60d8267f8f89c128e17f5aaecb0294a7853d/src/Integration/Spiral/SpiralView/Bootloader/SpiralViewBootloader.php#L17-L34

    This way we are only supporting the NativeEngine, which maybe is not the expected Engine, as StemplerEngine is I think the default one used by Spiral but that sadly did throw an error:

    dependency "locale" not found.

    Maybe instead it would be better directly call from the ViewManager, we need debug the exists $this->views->renderer call to revalidate this.

    Framework: Spiral 
    opened by alexander-schranz 1
  • Checking for Best Practices in Laminas Module creation

    Checking for Best Practices in Laminas Module creation

    I'm not yet sure if my Module.php are using best practices.

    Also not sure what the best way of addExtension in Latte and Twig is:

    • https://github.com/schranz-templating/templating/pull/5#discussion_r950609994

    Would be nice if somebody of Laminas Core Team could have a look at the existing Module.php definition of Latte: https://github.com/schranz-templating/templating/blob/0.1/src/Integration/Laminas/Latte/Module.php

    Was also linked to delegators: https://docs.laminas.dev/laminas-servicemanager/delegators/ but not sure if that can solve extension registry problem as it is more like service registration.

    Update: After some discussions the extensions config is fine. For modules there could be two other ways which I got following response:

    • Define a plugin manager for the component. These use SM configuration, and the component then pulls from the plugin manager when it needs an extension.
    • Compose an event manager and trigger an event. In the MVC, modules then attach listeners to that event (or, in Mezzio, you use a PSR-14 dispatcher, and wire in listeners in your listener provider).
    Framework: Laminas 
    opened by alexander-schranz 1
  • Refractor Spiral View Integration using ViewManager

    Refractor Spiral View Integration using ViewManager

    This will refractoring the SpiralViewRenderer using the ViewManager this way the ViewManager decides which templates to be rendered. Which will automatically add supports for Stempler template engine which is the default one for Spiral.

    fixes #55

    Framework: Spiral 
    opened by alexander-schranz 0
  • Fix Twig and Spiral View Bootloader

    Fix Twig and Spiral View Bootloader

    Fixes get the TwigEngine and NativeEngine from the Container initialized. The current implementation via directly get the TwigEngine service throws an error:

    [Spiral\Views\Exception\EngineException] No associated environment found. in /Users/alexanderschranz/Documents/Projects/templating/examples/usages/spiral/vendor/spiral/twig-bridge/src/TwigEngine.php:74

    Framework: Spiral 
    opened by alexander-schranz 0
  • Register Spiral Twig package

    Register Spiral Twig package

    The spiral twig integration was forgot to register correctly. This is done in this PR and creates a new subtree splited repo: https://github.com/schranz-templating/spiral-twig-integration

    Engine: Twig Framework: Spiral 
    opened by alexander-schranz 0
  • Add Spiral Twig Integration

    Add Spiral Twig Integration

    Add Twig Renderer integration into the Spiral Framework.

    Sadly there are 2 issues currently:

    • https://github.com/schranz-templating/templating/issues/41
    • https://github.com/schranz-templating/templating/issues/42
    Engine: Twig Framework: Spiral 
    opened by alexander-schranz 0
  • Mezzio: Rename Mezzio Adapter and Integration to MezzioTemplate

    Mezzio: Rename Mezzio Adapter and Integration to MezzioTemplate

    Similar to LaminasView and SpiralView the Mezzio adapter should be renamed to MezzioTemplateAdapter to make clear its the integration of Mezzio/Template namespace.

    Framework: Mezzio 
    opened by alexander-schranz 0
  • Add a `TemplateFunctionProviderInterface` for better Framework integration

    Add a `TemplateFunctionProviderInterface` for better Framework integration

    Beside the TemplateRendererInterface a separate package is in mind for a total different usecase then the exist Renderer. It is targeting Framework authors which want to provide Framework functionality to different Template engines.

    Most PHP Frameworks provides for there Template engines some functions commonly is something like generate a URL based on a named Route. In most Template engines this kind of things are handled via Extensions like in Twig or Latte.

    There are currently some issues with a TemplateFunctionProviderInterface abstraction.

    A. Different implementation of TemplateFunction

    The most common Template engines which does not have such implementation of Extension is Blade. Blade work the way that you can access all PHP functions and methods as it is {{ any_method($part) }}, as this is just PHP code which has advantages and disadvantages. Blade is by default used in Laravel which make a lot of usage of Global Function to provide helpers which are used in PHP Code but also in the Template itself. With this opens two questions. A1 should a TemplateFunctionProviderInterface for Blade under Laravel just register Global Function. A2 should a TemplateFunctionProviderInterface for Blade under different decorate Blade emulate global functions. A different way could be used that TemplateFunctionProviderInterface provides in Blade instead of functions Blade directives but as there usage is very different I'm not sure here. Other template engine like Spiral Stempler uses directives more often for things like route generation like here, so how this kind of mechanism should be implemented for this kind of engines is very complicated.

    B. Not all Template engines has extensions

    This is also the part why it make sense that the whole TemplateFunctionProviderInterface is totally seperate from the Rendering of templates. Library and Framework authors should keep in mind that not all Template engines so they always should have the possibility todo the things already in the controller which is the way why the TemplateRendererInterface is also small and should be keep small. That way this Controller can not support only rendering the content via any template engine but also provide the data as JSON for any API based data receivers.
    Still from a Framework perspective a TemplateFunctionProviderInterface make sense so atleast a few engines can has full access to all available Template Functions of a Framework


    How could a TemplateFunctionProviderInterface look like?

    As background of CMS where a lot of TwigExtension exist we did see a lot difference in performance how many Twig Extensions are registered. This means the TemplateFunctionProviderInterface should solve this issue that providing which functions are available does not required to initialize the Service. It is very common how in twig the twig.runtime works. A TemplateFunctionPRoviderInterface requires a static function this means the class don't need to initialized when it is checked what functions exist. Example:

    <?php
    
    namespace App\Templating\FunctionProvider;
    
    use Schranz\Templating\TemplateFunctionProvider\TemplateFunctionProviderInterface;
    
    class MyFunctionProvider implements TemplateFunctionProviderInterface
    {
        /**
         * @return iterable<string, string> FCQNorServiceId and Method Name
         */
        public static function getFunctions(): iterable
        {
             return [
                  'my_method' => new TemplateFunction(MyFunctionProvider::class, 'myMethod'),
             ];
        }
        
        public function myMethod(string $text): string
        {
            return $text + '-modified';
        }
    }
    

    There will then be a TwigExtension for example which will be a Bridge to all TemplateFunctionProvider and uses a PSR Container to access the service:

    namespace App\Twig;
    
    use Psr\Container\ContainerInterface;
    use Twig\Extension\AbstractExtension;
    use Twig\TwigFilter;
    
    class TwigFunction extends AbstractExtension
    {
        // maybe $providerClasses and $container can be combined but not sure
        public function __construct(private array $providerClasses, ContainerInterface $container)
        {
        }
    
        public function getFunctions()
        {
            $functions = [];
            foreach ($this->providerClasses as $class) {
                 foreach ($class::getFunctions() as $functionName => $function) {
                     $functions[] = new TwigFunction($functionName, function($params...) {
                          $this->callFunctionProvider($function, params);
                     });
                 }
            }
        
            return $functions;
        }
    
        public function callFunctionProvider(TemplateFunction $function, $params)
        {
            $serviceName = $function->getServiceName();
            $methodName = $function->getMethodName();
    
            $service = $this->container($serviceName); // only when really used a TemplateProvider will be initialized here
        
            return $service->{$methodName}(...$params);
        }
    }
    
    Feature 
    opened by alexander-schranz 0
  • Add check for outdated dependencies

    Add check for outdated dependencies

    We should be notified if there are new versions of specific engines and framework available. So the integrations and adapter could be updated to the new versions.

    Code Quality 
    opened by alexander-schranz 0
  • Add Integrations for Pimple based Frameworks

    Add Integrations for Pimple based Frameworks

    For legacy project it make sense to provided integrations also for Pimple based frameworks. This would for example be Silex.

    https://github.com/silexphp/Pimple

    Mustache is for example also provided for Pimple: https://github.com/bobthecow/mustache-silex-provider/blob/master/src/Mustache/Silex/Provider/MustacheServiceProvider.php

    New Framework 
    opened by alexander-schranz 0
Releases(0.1.0)
  • 0.1.0(Nov 14, 2022)

    This is the first Version of the package check the README of the project for more informations about the Project.

    With this release about 55 packages under the schranz-templating namespace are released.

    First supported Template Engines via Adapter packages:

    • ✅ Twig (schranz-templating/twig-adapter)
    • ✅ Blade (schranz-templating/blade-adapter)
    • ✅ Latte (schranz-templating/latte-adapter)
    • ✅ Plates (schranz-templating/plates-adapter)
    • ✅ Smarty (schranz-templating/smarty-adapter)
    • ✅ Handlebars (schranz-templating/handlebars-adapter)
    • ✅ Mustache (schranz-templating/mustache-adapter)

    First supported Framework Integrations

    • ✅ Symfony (Twig, Blade, Latte, Plates, Smarty, Handlebars, Mustache)
    • ✅ Laravel (Twig, Blade, Latte, Plates, Smarty, Handlebars, Mustache)
    • ✅ Spiral (Twig, Blade, Latte, Plates, Smarty, Handlebars, Mustache, Spiral View) (thx @butschster for the Feedback)
    • ✅ Laminas (Twig, Blade, Latte, Plates, Smarty, Handlebars, Mustache, Laminas View)
    • ✅ Mezzio (Twig, Blade, Latte, Plates, Smarty, Handlebars, Mustache, Mezzi Template)

    Usage for Symfony Projects

    To use the integration in the Symfony Framework the following packages are currently provided, which will register the adapter service and integration of the selected template engine:

    composer require schranz-templating/symfony-twig-integration
    composer require schranz-templating/symfony-blade-integration
    composer require schranz-templating/symfony-latte-integration
    
    composer require schranz-templating/symfony-plates-integration
    composer require schranz-templating/symfony-smarty-integration
    composer require schranz-templating/symfony-handlebars-integration
    composer require schranz-templating/symfony-mustache-integration
    

    Usage for Laravel Projects

    To use the integration in the Laravel Framework the following packages are currently provided, which will register the adapter service and integration of the selected template engine:

    composer require schranz-templating/laravel-spiral-view-integration
    
    composer require schranz-templating/laravel-twig-integration
    composer require schranz-templating/laravel-blade-integration
    composer require schranz-templating/laravel-latte-integration
    
    composer require schranz-templating/laravel-plates-integration
    composer require schranz-templating/laravel-smarty-integration
    composer require schranz-templating/laravel-handlebars-integration
    composer require schranz-templating/laravel-mustache-integration
    

    Usage for Laminas Projects

    To use the integration in the Laminas Framework the following packages are currently provided, which will register the adapter service and integration of the selected template engine:

    composer require schranz-templating/laminas-laminas-view-integration
    
    composer require schranz-templating/laminas-twig-integration
    composer require schranz-templating/laminas-blade-integration
    composer require schranz-templating/laminas-latte-integration
    
    composer require schranz-templating/laminas-plates-integration
    composer require schranz-templating/laminas-smarty-integration
    composer require schranz-templating/laminas-handlebars-integration
    composer require schranz-templating/laminas-mustache-integration
    

    Usage for Mezzio Projects

    To use the integration in the Mezzio Framework the following packages are currently provided, which will register the adapter service and integration of the selected template engine:

    composer require schranz-templating/mezzio-mezzio-template-integration
    
    composer require schranz-templating/mezzio-twig-integration
    composer require schranz-templating/mezzio-blade-integration
    composer require schranz-templating/mezzio-latte-integration
    
    composer require schranz-templating/mezzio-plates-integration
    composer require schranz-templating/mezzio-smarty-integration
    composer require schranz-templating/mezzio-handlebars-integration
    composer require schranz-templating/mezzio-mustache-integration
    

    Usage for Spiral Projects

    To use the integration in the Spiral Framework the following packages are currently provided, which will register the adapter service and integration of the selected template engine:

    composer require schranz-templating/spiral-spiral-view-integration
    
    composer require schranz-templating/spiral-twig-integration
    composer require schranz-templating/spiral-blade-integration
    composer require schranz-templating/spiral-latte-integration
    
    composer require schranz-templating/spiral-plates-integration
    composer require schranz-templating/spiral-smarty-integration
    composer require schranz-templating/spiral-handlebars-integration
    composer require schranz-templating/spiral-mustache-integration
    
    Source code(tar.gz)
    Source code(zip)
Owner
Schranz Templating
A template abstraction prototype for php template engines.
Schranz Templating
PHP Template Attribute Language — template engine for XSS-proof well-formed XHTML and HTML5 pages

PHPTAL - Template Attribute Language for PHP Requirements If you want to use the builtin internationalisation system (I18N), the php-gettext extension

PHPTAL 175 Dec 13, 2022
PHP template engine for native PHP templates

FOIL PHP template engine, for PHP templates. Foil brings all the flexibility and power of modern template engines to native PHP templates. Write simpl

Foil PHP 167 Dec 3, 2022
A PHP project template with PHP 8.1, Laminas Framework and Doctrine

A PHP project template with PHP 8.1, Laminas Framework and Doctrine

Henrik Thesing 3 Mar 8, 2022
Twig, the flexible, fast, and secure template language for PHP

Twig, the flexible, fast, and secure template language for PHP Twig is a template language for PHP, released under the new BSD license (code and docum

Twig 7.7k Jan 1, 2023
Smarty is a template engine for PHP, facilitating the separation of presentation (HTML/CSS) from application logic.

Smarty 3 template engine smarty.net Documentation For documentation see www.smarty.net/docs/en/ Requirements Smarty can be run with PHP 5.2 to PHP 7.4

Smarty PHP Template Engine 2.1k Jan 1, 2023
Native PHP template system

Plates Plates is a native PHP template system that's fast, easy to use and easy to extend. It's inspired by the excellent Twig template engine and str

The League of Extraordinary Packages 1.3k Jan 7, 2023
☕ Latte: the intuitive and fast template engine for those who want the most secure PHP sites.

Latte: amazing template engine for PHP Introduction Latte is a template engine for PHP which eases your work and ensures the output is protected again

Nette Foundation 898 Dec 25, 2022
View template engine of PHP extracted from Laravel

Blade 【简体中文】 This is a view templating engine which is extracted from Laravel. It's independent without relying on Laravel's Container or any others.

刘小乐 143 Dec 13, 2022
A complete and fully-functional implementation of the Jade template language for PHP

Tale Jade for PHP Finally a fully-functional, complete and clean port of the Jade language to PHP — Abraham Lincoln The Tale Jade Template Engine brin

Talesoft 91 Dec 27, 2022
A ready-to-use Model View Controller template in PHP

PHP-MVC-Template A ready-to-use Model View Controller template in PHP Use this repo as a template! (Or clone it) Start to configure your MVC file Afte

Loule | Louis 20 Dec 26, 2022
Provides a GitHub repository template for a PHP package, using GitHub actions.

php-package-template Installation ?? This is a great place for showing how to install the package, see below: Run $ composer require ergebnis/php-pack

null 280 Dec 27, 2022
The free-to-use template for your Imagehost-website made with PHP, HTML and CSS!

The free-to-use template for your Imagehost-website made with PHP, HTML and CSS! Some information before we start This repo is only code related, to a

Ilian 6 Jul 22, 2022
The free-to-use template for your Imagehost-website made with PHP, HTML and CSS!

The free-to-use template for your Imagehost-website made with PHP, HTML and CSS! Some information before we start This repo is only code related, to a

Ilian 6 Jul 22, 2022
⚡️ Simple and fastly template engine for PHP

EasyTpl ⚡️ Simple and fastly template engine for PHP Features It's simple, lightweight and fastly. No learning costs, syntax like PHP template It is s

PHPPkg 19 Dec 9, 2022
Twig Template Engine to Phalcon PHP

Twig Template Engine to Phalcon PHP

Vinicius 4 Oct 7, 2022
Liquid template engine for PHP

Liquid is a PHP port of the Liquid template engine for Ruby, which was written by Tobias Lutke. Although there are many other templating engines for PHP, including Smarty (from which Liquid was partially inspired)

Harald Hanek 230 Aug 18, 2022
FyreView is a free, open-source template rendering library for PHP.

FyreView FyreView is a free, template rendering library for PHP. Table Of Contents Installation Methods Layouts Paths Helper Registry Helpers CSP Form

Elusive 1 Jul 30, 2022
A lightweight template parser used by PyroCMS.

Lex Lex is a lightweight template parser. Lex is released under the MIT License and is Copyrighted 2011 - 2014 PyroCMS Team. Change Log 2.3.2 Convert

PyroCMS 102 Dec 21, 2022
Laravel package template

REPLACE Simple and flexible package template. Usage Replace all occurances of REPLACE (case sensitive) with the name of the package namespace. E.g. th

ARCHTECH 56 Aug 15, 2022