Native PHP template system



Maintainer Source Code Latest Version Software License Build Status Coverage Status Quality Score Total Downloads

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 strives to bring modern template language functionality to native PHP templates. Plates is designed for developers who prefer to use native PHP templates over compiled template languages, such as Twig or Smarty.


  • Native PHP templates, no new syntax to learn
  • Plates is a template system, not a template language
  • Plates encourages the use of existing PHP functions
  • Increase code reuse with template layouts and inheritance
  • Template folders for grouping templates into namespaces
  • Data sharing across templates
  • Preassign data to specific templates
  • Built-in escaping helpers
  • Easy to extend using functions and extensions
  • Framework-agnostic, will work with any project
  • Decoupled design makes templates easy to test
  • Composer ready and PSR-2 compliant


Plates is available via Composer:

composer require league/plates


Full documentation can be found at


composer test


Please see CONTRIBUTING for details.


If you discover any security related issues, please email [email protected] instead of using the issue tracker.



The MIT License (MIT). Please see License File for more information.

  • Cleaner templates via new compiling stage

    Cleaner templates via new compiling stage

    I'm seriously considering introducing a compiling stage to Plates, with two main goals:

    1. To finally allow proper auto-escaping
    2. To cleanup the template code

    I know what you're thinking: "What, a parsing stage for native PHP templates? Isn't that exactly what we're trying to avoid?" It's a fair question. But, I think a bigger question needs to be asked first: Why do developers prefer native PHP templates? I believe it's because they don't want to learn a new syntax. They are comfortable working with PHP, they know the functions available to them, and they can get the job done quick. The lack of compiling stage is just an added benefit, although given how compiled template engines handle caching, this is really a moot point.

    Generally compiled template engines have a unique, custom syntax. But what if Plates templates remained 100% pure, native PHP, and the compiling stage simply helped make these templates safer (auto-escaping) and nicer to read? I think that could be pretty awesome!

    Proposed compiling stage

    • Automatically insert an escape function inside all PHP short tags:
      • <?=$name?> becomes <?php echo $this->escape($name) ?>
      • To output "raw" variables, simply use regular tags: <? echo $name ?>
      • Auto-escaping can be enabled/disabled
    • Automatically add $this-> to all template functions:
      • <? layout('template') ?> becomes <?php $this->layout('template') ?>
      • Completely removes the need to ever use $this in templates
      • Still has all the benefits that an object-based template system provides
    • Automatically convert short open tags to regular tags:
      • <? becomes <?php
      • Short open tags make templates cleaner/more legible, except they're often disabled
      • This allows them to be used all the time, even when they're disabled!
      • Again, no new syntax—these are documented tags

    The result

    • 100% native PHP templates
    • Proper auto-escaping (only on outputted variables)
    • No more $this pseudo-variable
    • The ability to use short open tags


    A new Plates 3.0 template:

    <? layout('template', ['title' => 'User Profile']) ?>
    <h1>User Profile</h1>
    <p>Hello, <?=$name?></p>
    <? start('sidebar') ?>
             <li><a href="/link">Link</a></li>
             <li><a href="/link">Link</a></li>
             <li><a href="/link">Link</a></li>
    <? stop() ?>

    A compiled Plates 3.0 template:

    <?php $this->layout('layouts/page', ['title' => 'User Profile']) ?>
    <h1>User Profile</h1>
    <p>Hello, <?php echo $this->escape($name); ?></p>
    <?php $this->start('sidebar') ?>
             <li><a href="/link">Link</a></li>
             <li><a href="/link">Link</a></li>
             <li><a href="/link">Link</a></li>
    <?php $this->stop() ?>

    What do you think?

    opened by reinink 50
  • CS Fixes

    CS Fixes

    CS fixes to comply with the other league repos.

    opened by GrahamCampbell 23
  • addFolder is not what i want: how do i allow searching in more then 1 default directory?

    addFolder is not what i want: how do i allow searching in more then 1 default directory?

    I've an array of 4 directories, is it possible to have them as default search paths instead of just 1 ?

    opened by badpenguin 21
  • Accessing template variables without $this

    Accessing template variables without $this

    This request keeps coming up:

    Can we access template variables without the $this pseudo-variable?

    As discussed in #9, this is not possible with template functions, and therefore it seemed unwise to do this with template variables (as it would create inconsistency between how these two are accessed).

    Further, prior to the changes made to nesting and layouts, accessing variables without $this wasn't even possible. However, because nested templates now have their own variable scope, this may actually be be possible...with some caveats to sections. Consider this example:

    <?php $this->start('content') ?>
        <p>Hello <?=$this->e($this->name)?></p>
    <?php $this->end() ?>

    The contents of this section will be placed into the variable <?=$this->content?>. Generally, sections are used with inheritance, in which case there shouldn't be an issue. The section variables can be extracted before the layout is rendered, making the content available in the layout's local scope ($content).

    However, if you want to use this variable in the same template, this will not be possible. For example:

    <?php $this->start('content') ?>
        <p>Hello <?=$this->e($this->name)?></p>
    <?php $this->end() ?>
    <!-- This will not work: -->

    There are two ways around this. You could access this variable the old way (<?=$this->content?>), but that now creates an odd and very inconsistent approach to accessing variables. Alternatively, section variables could be accessed using a new template function, such as: <?=$this->section('content')?>. I'd be inclined to say, for consistency's sake, that all section variables should be accessed using this new section() function. For example:

    <div id="content">
    <?php if ($this->section('sidebar')): ?>
        <div id="sidebar">
    <?php endif ?>

    With the sections issue out of the way, does it now make sense to encourage (force) everyone to access variables without the $this pseudo-variable? We could theoretically allow both approaches, and developers can choose which one they prefer. Personally, think that is a bad idea since it creates inconsistency in the templates. I'd prefer to simply choose which approach is better, and force that. This would clearly be a breaking change, meaning a version bump (3.0).

    So, is everyone okay with having template functions accessed differently than template variables?

    <h1>Hello, <?=$this->e($name)?></h1>
    opened by reinink 21
  • Make template escape methods public

    Make template escape methods public

    The Plates documentation has a section on making the template object available to extensions. The methods of that object used to escape output would be useful to extensions, but are presently protected, preventing them from being accessible in that scope. Not sure that it matters, but this happens under Plates 3.1.1 and PHP 5.6.10.

    // template.php
    <?php echo $this->foo(); ?>
    // Extension.php
    class Extension implements \League\Plates\Extension\ExtensionInterface
        public $template;
        public function register(\League\Plates\Engine $engine)
            $engine->registerFunction('foo', [$this, 'foo']);
        public function foo()
            return $this->template->e('foo');
    // test.php
    $engine = new \League\Plates\Engine;
    $engine->addFolder('foo', __DIR__);
    $engine->loadExtension(new Extension);
    echo $engine->render('foo::template');
    PHP Fatal error:  Uncaught exception 'LogicException' with message 
    'The template function "e" was not found.' in 
    Stack trace:
    #0 vendor/league/plates/src/Engine.php(196):
    #1 vendor/league/plates/src/Template/Template.php(70):
    #2 test.php(16):
      League\Plates\Template\Template->__call('e', Array)
    #3 test.php(16):
    #4 [internal function]: Extension->foo()
    #5 vendor/league/plates/src/Template/Func.php(105):
      call_user_func_array(Array, Array)
    #6 vendor/league/plates/src/Template/Template.php(70):
      League\Plates\Template\Func->call(Object(League\Plates\Template\Template), Array)
    #7 . in vendor/league/plates/src/Template/Functions.php on line 63
    opened by elazar 20
  • Setting Layout Once Per Controller

    Setting Layout Once Per Controller

    So, as I'm looking through the docs I don't see way to set a global layout. Is there? What I mean: setting a layout in the main controller that all other controllers use and/or extend then each template would use that layout instead of defining it in each and every template explicitly.

    Changing the layout of a particular set of templates I'd have to go through and edit all of those files. This doesn't seem ideal. Or even just passing a side bar data for a particular layout has to be done by passing the side bar data to each template and from each template to the layout. This seems very redundant. Or am I missing something?

    question discussion 
    opened by KnightYoshi 20
  • 'Translation' functionality

    'Translation' functionality

    Can mimic the functionality of translating the static (and dynamic?) content inside a template. It takes a 1 dimensional array containing key => value.


    • Separates static from dynamic content. - Links texts, meta content and etc.
    • Can help in generating language specific URLs. - The value is set during instantiation, see:
    • Language changing. - All data for a language changing plugin are presented
    • Makes templates syntax prettier. (depends on implementation)


    • Is not extendable
    • Does not support anything but PHP arrays. (Yet)
    • Doesn't do much.
    opened by DaGhostman 14
  • Section push not showing after section start

    Section push not showing after section start

    Hope this makes since, first time posting. Using Plates 4 alpha. Please excuse bad coding, Im working on it. Ok so in the main template.php file I load initial sections through a include file like so:


    Inside page-section.php has all the default content for each section I want to load in template.php. So in the header section of template.php I have:


    The problem is farther down the template.php I have some code to load side modules, like so:

    foreach($side_modules AS $curr_module):
    $view->insert('modules/' .$curr_module['modfile']);

    In some of the module files I want to push data like needed JS or CSS code/includes to the header_codetop section, for example modules/site-links.php:

    <?php $view->push('header_codetop') ?>
    <script src="/test.js"></script>
    <?php $view->stop() ?>
    //HTML content goes here

    But it doesnt work. It only works if the push happens before:


    So if I want to push content to a section in the footer, which is below the foreach loop, it works just fine. Is there a way to make the push happen later down the process so I can push data to a section at anytime on the page? Or maybe, hopefully, Im doing something wrong?

    EDIT: Also I understand that when Im doing this:


    Its echoing out the value for section header_codetop. However I was hoping there was a different way of not echoing it right away, instead it can wait until everything is rendering and echo it all out at the end. Or maybe Im using plates all wrong and there is a better way of doing what Im trying to do?

    opened by brightboxtech 14
  • Update composer.json

    Update composer.json

    opened by GrahamCampbell 13
  • Escape multiple variables by reference

    Escape multiple variables by reference

    I understand that auto-escaping isn't feasible, but I believe we could still improve things in this area by simply offering a method to mass-escape multiple variables at once. For example, we could then have this at the top of a template:

    $this->escapeMultiple($foo, $bar, $baz);

    And that would allow the actual template code to be much cleaner:


    This way the template author still has to think about escaping, but they only have to do it once at the top. If they've escaped some variables and not others, this is nicely self-documenting, as they can glance back up to the top if they need to check whether a particular variable has been escaped already. It's not quite as slick as full-blown auto-escaping, but this feels like it would be a middle ground that's better than the current requirement of manually escaping every single time, without running into the problems associated with auto-escaping.

    I tried to write an extension to add this (which was going to support both strings and arrays of strings), but discovered it seems to be impossible to add as an extension given the current architecture, because template functions cannot receive data by reference.

    Any chance of this being added as an official feature? If not, any chance of making it possible for template functions to get data by reference, so I can at least finish my extension?

    opened by cdCorey 13
  • ResolveTemplatePath not exist ?

    ResolveTemplatePath not exist ?

    Docs says: ?

    opened by mhf-ir 0
  • Added 'Plates Sections Insertion' extension

    Added 'Plates Sections Insertion' extension

    I've developed a simple extension to set/push/unshift sections content into templates from the controller. I think it could be useful for other users and I'd like to share it: Plates Sections Insertion

    opened by kros 1
  • move path resolve from name class

    move path resolve from name class

    I proposing that the template path resolution should outside of the Template Name class and into the ResolvePath classes

    opened by gabrielsolomon 0
  • Move to a Twig Loader concept

    Move to a Twig Loader concept


    I really like the new Theme functionality.

    But i was wondering if it would be interesting to move to a Loader concept similar to Twig and incorporate both the folder and theme functionality in it. This would mean that all the template resolve would be incapsulated in one place.

    I was thinking something in the like of the code below.

    If this is interesting i would be happy to make a complete PR

    FilesystemResolveTemplatePath {
         * Hint path delimiter value.
         * @var string
        public const HINT_PATH_DELIMITER = '::';
         * Identifier of the main namespace.
         * @var string
        public const MAIN_NAMESPACE = '__main__';
         * The array of active view paths.
         * @var array
        protected $paths = [];
         * Get the fully qualified location of the view.
         * @param string $name
         * @return string
        public function find($name)
            list($namespace, $view) = $this->parseName($name);
            return $this->findNamespacedView($view, $namespace);
         * Adds a path where templates are stored.
         * @param string $path A path where to look for templates
         * @param string $namespace A path namespace
         * @return void
        public function addPath($path, $namespace = self::MAIN_NAMESPACE)
            $this->paths[$namespace][] = rtrim($path, '/\\');
         * Prepends a path where templates are stored.
         * @param string $path A path where to look for templates
         * @param string $namespace A path namespace
         * @return void
        public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
            $path = rtrim($path, '/\\');
            if (!isset($this->paths[$namespace])) {
                $this->paths[$namespace][] = $path;
            } else {
                array_unshift($this->paths[$namespace], $path);
         * @param $name
         * @param string $namespace
         * @return array
        public function parseName($name, $namespace = self::MAIN_NAMESPACE)
            if ($this->hasNamespaceInformation($name = trim($name))) {
                return $this->parseNamespacedName($name);
            return [$namespace, $name];
         * Get the segments of a template with a named path.
         * @param string $name
         * @return array
         * @throws \InvalidArgumentException
        protected function parseNamespacedName($name)
            $segments = explode(static::HINT_PATH_DELIMITER, $name);
            if (count($segments) != 2) {
                throw new InvalidArgumentException("View [$name] has an invalid name.");
            if (!isset($this->paths[$segments[0]]) || count($this->paths[$segments[0]]) < 1) {
                throw new InvalidArgumentException("No path defined for namespace [{$segments[0]}].");
            return $segments;
         * Get the path to a template with a named path.
         * @param string $name
         * @param $namespace
         * @return string
        protected function findNamespacedView($name, $namespace)
            return $this->findInPaths($name, $this->paths[$namespace]);
         * Find the given view in the list of paths.
         * @param string $name
         * @param array $paths
         * @return string
         * @throws \InvalidArgumentException
        protected function findInPaths($name, $paths)
            foreach ((array)$paths as $path) {
                $file = $this->getViewFilename($name);
                if (file_exists($viewPath = $path . '/' . $file)) {
                    return $viewPath;
            throw new TemplateNotFound(
                'View [' . $name . '] not found in paths [' . implode(', ', $paths) . '].'
         * Returns whether or not the view name has any hint information.
         * @param string $name
         * @return bool
        public function hasNamespaceInformation($name)
            return strpos($name, static::HINT_PATH_DELIMITER) > 0;
    opened by gabrielsolomon 2
  • Components


    (placeholder issue/task for defining the components).

    You can view an example of the components in use on a demo project here

    opened by ragboyjr 1
  • Setup


    Right now the only League project using a custom domain is this one ( There really isn't any reason for this.

    • [ ] Add the CNAME DNS record
    • [ ] Update /docs/CNAME
    • [ ] Figure out 301 redirects for all the old addresses (this is the hard part)
    opened by reinink 2
  • v3.4.0(Dec 25, 2020)


    • Added new unshift method in templates to support prepending content to sections (thanks @kozubsky)
    • Added support for PHP8 (thanks @roxblnfk)


    • Dropped explicit support for php 5. PHP 7/8 is allowed in composer, and only php 7.3-8.0 are tested in CI pipeline.

    Internal Changes

    • Minor modifications to repo workflow for CI with GitHub Actions instead of Travis
    • Migrated docs from Jekyll to Hugo
    Source code(tar.gz)
    Source code(zip)
  • v4.0.0-alpha(Feb 6, 2018)

    EDIT (12/24/2020): This release has been abandoned. Some of this work will be merged into the v3 branch, but most of it has been scrapped. This tag will still be available, but a version 4 will not be based off of this alpha release.

    v4 has been a complete rewrite in the plates system. It's fairly backwards compatible, but a lot of the internals have changed, and we still have a decent amount of features and work to do for v4.

    Significant Changes

    • Templates are Immutable VO's
    • Rendering is handled via RenderTemplate interfaces
    • Extensions are first class citizens
    • The Engine is now a small wrapper for an IoC Container

    New Features

    • RenderContext API for defining composable functions and more
    • Components
    • Powerful and customizable naming strategies for dynamic base paths
    • Multi folder fallbacks
    • Relative and Absolute Path templates
    • Better Error Handling
    • Default Layouts
    • Deep Sections #169
    • Template Composers
    • Static File Rendering
    • Image/Base64Encoding Rendering
    • And probably a few more ;p

    Documentation is lacking for many of these features. Contributions are welcome! The best way to learn about the features it to look at the tests and examples.

    Source code(tar.gz)
    Source code(zip)
  • 3.3.0(Dec 28, 2016)

  • 3.2.0(Dec 27, 2016)

    • Fixed an issue where template functions were not accessible from extensions.
    • Fixed an issued with the URI extension throwing errors when it shouldn't.
    • Added the ability to get all template data by calling $template->data().
    • Added the ability to render a template via the toString() magic method.
    • Added the ability to run the tests using composer test.
    • Improvements to error handling when rendering templates.
    • Various coding style, CI and documentation improvements.
    Source code(tar.gz)
    Source code(zip)
  • 3.1.1(Jul 9, 2015)

  • 3.1.0(Oct 21, 2014)

  • 3.0.3(Oct 20, 2014)

    • Added ability to define the default content of a section.
    • Various code improvements (cleanup DocBlocks, class simplification, add Composer keywords, etc).
    Source code(tar.gz)
    Source code(zip)
  • 3.0.2(Sep 30, 2014)

    • Added all missing tests.
    • Improved custom function name validation.
    • Fixed bug with fallback folders, where the file extension wasn't being applied.
    • Improved error handling in Template class.
    Source code(tar.gz)
    Source code(zip)
  • 3.0.1(Sep 28, 2014)

  • 3.0.0(Sep 27, 2014)

    • Added ability to share data across templates.
    • Added ability to preassign data to specific templates.
    • Added ability to create one-off template functions, without using an extension.
    • Added new folder "fall backs", where missing folder templates will fall back to the default folder.
    • Added new render() method to Engine class, improving the use of the Engine as the primary API.
    • Templates variables are now accessed without the $this pseudo-variable.
    • Total overhaul to how extensions are registered. Replaced getFunctions() method with new register() method.
    • Section content is no longer assigned to template variables. Use the the section() function instead.
    • Renamed section end() function to stop(). This fits more appropriately with the start() function.
    • Renamed get() function to fetch().
    • Renamed pathExists() method in the Engine class to exists().
    • Renamed getTemplatePath() method in the Engine class to path().
    • Renamed makeTemplate() method in the Engine class to make().
    • Removed the ability to assign template data directly to the Template class. For example: $this->name = 'Jonathan'. This applies both within and outside of templates. Use the data() method instead.
    • Removed getEngine() method from the Template class. There's no reason to need this anymore.
    • Removed addFolders() method from the Engine() class.
    • Removed unloadExtension() and unloadExtensionFunction() methods from the Engine() class.
    Source code(tar.gz)
    Source code(zip)
  • 2.1.0(Apr 2, 2014)

    • Improved DocBlocks throughout the library.
    • The insert() functionality has been moved to a new extension, called Nest.
    • A new get() function was also added with this extension, which offers an alternative syntax for nesting templates.
    • Improved error messages.
    • A new error check which prevents the calling of the render() function from within templates themselves. If this functionally is required, use the nesting functions instead.
    • Added a clearer error message to the content() function when calling it from a non layout template.
    • Added a clearer error message to the batch() extension function when a provided function does not exist.
    • Fixed a bug in the engine where it was possible to overwrite a default extension when loading extensions.
    Source code(tar.gz)
    Source code(zip)
  • 2.0.0(Mar 31, 2014)

    • Added stacked layouts, allowing even further simplification and organization of templates.
    • Added new unloadExtension() and unloadExtensionFunction() methods to the Engine() class.
    • Added getEngine() method to the Template class.
    • Added addFolders() and loadExtensions() methods to the Engine() class.
    • Nested templates are now self-contained objects, with their own variables and layouts.
    Source code(tar.gz)
    Source code(zip)
  • 1.0.8(Feb 20, 2014)

  • 1.0.9(Feb 20, 2014)

  • 1.0.10(Feb 20, 2014)

  • 1.0.11(Feb 20, 2014)

  • 1.2.1(Feb 20, 2014)

  • 1.1.0(Jan 31, 2014)

The League of Extraordinary Packages
A group of developers who have banded together to build solid, well tested PHP packages using modern coding standards.
The League of Extraordinary Packages
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 165 Nov 17, 2021
The Templating component provides all the tools needed to build any kind of template system.

Templating Component The Templating component provides all the tools needed to build any kind of template system. It provides an infrastructure to loa

Symfony 982 Nov 23, 2021
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.3k Nov 24, 2021
Smarty is a template engine for PHP, facilitating the separation of presentation (HTML/CSS) from application logic.

Smarty 3 template engine Documentation For documentation see Requirements Smarty can be run with PHP 5.2 to PHP 7.4

Smarty PHP Template Engine 1.9k Nov 23, 2021
☕ 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 731 Nov 27, 2021
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.

刘小乐 145 Aug 13, 2021
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 93 May 4, 2021
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 6 Nov 19, 2021
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 260 Nov 24, 2021
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 5 Nov 3, 2021
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 5 Nov 3, 2021
⚡️ 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 9 Nov 26, 2021
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 103 Nov 15, 2021
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 47 Nov 24, 2021
Document templates Laravel package is intended for creating/managing user editable document template

Document Templates Introduction Document templates Laravel package is intended for creating/managing user editable document templates, with ability to

42coders 99 Nov 14, 2021
A SilverStripe Module with template methods to quickly make use of FocusPoint, LazySizes, and Object-fit

LazyFocusFit A SilverStripe module with template methods to quickly make use of FocusPoint, LazySizes and object-fit. Requirements PHP FocusPoint JS/C

Evans Hunt 8 Oct 12, 2021
Astroid Framework - Powerful Joomla Template Framework

Powerful framework for designers and developers to create responsive, fast & robust Joomla based websites and templates.

TemPlaza 9 Nov 23, 2021
A Mustache implementation in PHP.

Mustache.php A Mustache implementation in PHP. Usage A quick example: <?php $m = new Mustache_Engine(array('entity_flags' => ENT_QUOTES)); echo $m->re

Justin Hileman 3.1k Nov 17, 2021
Multi target HAML (HAML for PHP, Twig, )

Multi target HAML MtHaml is a PHP implementation of the HAML language which can target multiple languages. Currently supported targets are PHP and Twi

Arnaud Le Blanc 362 Aug 5, 2021