PHP template engine for native PHP templates

Overview

FOIL

PHP template engine, for PHP templates.


travis-ci status codecov.io license release


Foil brings all the flexibility and power of modern template engines to native PHP templates. Write simple, clean and concise templates with nothing more than PHP.

Key Features

  • Templates inheritance (you'll never miss Twig or Blade)
  • Clean, concise and DRY templates
  • Dozen of ready-made helper functions and filters
  • Easily extensible and customizable
  • Multiple template folders with file auto-discover or custom picking
  • Auto or manual data escape
  • Powerful context API (preassign data to templates using conditions)
  • Framework agnostic, centralized API for very easy integration
  • Composer ready, fully unit and functional tested, PSR-1/2/4 compliant

...and many more

Why?

Templates engines like Twig, or Blade are a great thing, really.

However, to use them one needs to learn another language with its own syntax and rules.

Moreover, using compiled engines to use even a simple PHP function one needs to write engine extension.

On its side, PHP is already a templating language, but honestly it's not a good one, because it's missing pivotal features of modern template engines, like template inheritance.


Requirements

Foil is framework agnostic, only thing needed is PHP 5.4+ and Composer to add Foil to you PHP project.


License

Foil is open source and released under MIT license. See LICENSE file for more info.

Question? Issues?

Foil is hosted on GitHub. Feel free to open issues there for suggestions, questions and real issues.

Who's Behind Foil

I'm Giuseppe, I deal with PHP since 2005. For questions, rants or chat ping me on Twitter (@gmazzap) or on "The Loop" (Stack Exchange) chat. Well, it's possible I'll ignore rants.

Comments
  • 0.6.4 is now repeating content sections within a loop

    0.6.4 is now repeating content sections within a loop

    0.6.3 was running perfectly for my code. The item in the loop were iterated properly. 0.6.4 is now just dumping the same first item for every iteration. all my code stayed the same. I just updated composer.

    File: project_item.foil

    <?php $this->section('itemsection')?>
    <div class="job clearfix pitem" style="page-break-inside: avoid" id="<?=$this->v('project.htmlid','')?>">
        <div class="<?=$this->col1_css ?>">
                <?= $this->insert($this->v('itemlogosectionview','partials/itemlogo_psup')); ?>
    
               <?php $this->section('projectyearsection')?>
                    <div class="year">
                    <?=$this->v('project.year','')?>
                    </div>
                <?php $this->replace()?>
    
                <?php $this->section('projectfeessection')?>
                    <div class="year">
                    <?=$this->v('project.fees')?>
                    </div>
                <?php $this->replace()?>
            </div>
        </div>
    <?php $this->replace() ?>
    

    The foil above was called from File: body.foil

    <?php foreach($this->majorProjects as $project):?>
        <?=$this->insert('partials/project_item',['project' => $project]) ?>
    <?php endforeach; ?>
    

    I suspect this change could be the reason, src/Section/Section.php [https://github.com/FoilPHP/Foil/compare/0.6.3...0.6.4]

    if (empty($this->mode)) {
                 $this->mode = self::MODE_REPLACE;
             }
    -        $this->content = ob_get_clean();
    +        $buffer = ob_get_clean();
    +        $this->content or $this->content = $buffer;
    +        $this->content = ($this->mode & self::MODE_APPEND) ? $buffer.$this->content : $this->content;
             if ($this->mode & self::MODE_OUTPUT) {
                 echo $this->content();
             }
    

    Please suggest. Thanks.

    bug 
    opened by thevikas 8
  • `supply()` template method does not work when same engine instance is used to render more templates

    `supply()` template method does not work when same engine instance is used to render more templates

    As per the title, here is my use case.

    /views/layouts/master.php

    <!DOCTYPE html>
    <html>
        <head>
            <title><?= $T->v('title', 'Foo Bar') ?></title>
        </head>
        <body>
            <main><?= $T->supply('main') ?></main>
        </body>
    </html>
    

    /views/default.php

    <?php $T->layout('layouts/master') ?>
    
    <?php $T->section('main') ?>
    
        <h1>Something</h1>
    
    <?php $T->stop() ?>
    

    This next bit is overly simplified, I am running a PHP-DI container inside a Wordpress theme with a PSR-7 router. But none of that should matter (I don't think).

    $engine = Foil::boot(['folders' => ['/views'], 'alias'   => 'T'])->engine();
    $html = $engine->render('default');
    

    The Result:

    <!DOCTYPE html>
    <html>
        <head>
            <title>Foo Bar</title>
        </head>
        <body>
            <main></main>
        </body>
    </html>
    

    Expected Result:

    <!DOCTYPE html>
    <html>
        <head>
            <title>Foo Bar</title>
        </head>
        <body>
            <main><h1>Something</h1></main>
        </body>
    </html>
    

    If I modify the master layout to look like this, I get the expected result:

    <!DOCTYPE html>
    <html>
        <head>
            <title><?= $T->v('title', 'Foo Bar') ?></title>
        </head>
        <body>
            <main>
                <?php $T->section('main') ?>
                <?php $T->stop() ?>
            </main>
        </body>
    </html>
    

    The issue appears to be here: https://github.com/FoilPHP/Foil/blob/master/src/Template/Template.php#L172

    $this->sections is empty. I have tried to follow how the sections are defined and added to the stack but between dependency injection, events, magic methods & the fact it's now 20mins past midnight. I got confused rather quickly. I will have another look in the morning with fresh eyes.

    All the same the supply method certainly doesn't appear to work or at least it doesn't work exactly like the Laravel Blade @yield syntax. Maybe I am missing something obvious??? I'll probably discover my error the second I hit the "Submit new issue" button.

    bug 
    opened by brad-jones 8
  • Prepend directories in the finder

    Prepend directories in the finder

    In some situations would be nice to have a method to "prepend" a folder to the current list of search folders. Example, let's say you have this 2 folders where to search for templates:

    $engine->addFolder('/templates/main_folder');
    $engine->addFolder('/templates/sub_folder');
    

    templates will be search firts in the folder 'main' and then, if not found, in "sub". what about if you want to add a folder in the beginning AFTER the initialization? That will be a nice improvements to add flexibility.

    Something like:

    $engine->prependFolder('/templates/plugin_folder');
    

    By the way, outstanding work in this project! thanks a lot!

    feature-request 
    opened by microstudi 8
  • Double render issue

    Double render issue

    Hi, I found a strange bug when the ->render() function is executed twice (or more) in the same script. Let's say you have this directory structure:

    index.php
    templates/base.php
    templates/page.php
    

    With this content in each file: index.php

    <?php
    
    require 'vendor/autoload.php';
    
    $engine = Foil\engine([
      'folders' => ['templates']
    ]);
    
    $page1 = $engine->render('page');
    
    $page2 = $engine->render('page');
    
    echo $page2;
    

    templates/base.php

    <?php $this->section('content') ?>
    BASE CONTENT
    <?php $this->stop() ?>
    

    templates/page.php

    <?php
    $this->layout('base');
    

    if you execute the index.php script, for instance, by command line: php index.php, this is the output obtained:

    BASE CONTENT
    
    BASE CONTENT`
    

    I.e. the 'content' section appears twice! When it should be only one line, isn't it? This is accumulative, if you have 3 ->render() calls, you can expect 3 repetitions of the section.

    Do you have a clue of why is this happening? Thanks

    bug 
    opened by microstudi 6
  • Trimming output?

    Trimming output?

    Hi!

    Thanks for creating Foil. It solves a big issue I had with Plates: lack of multi-folder support and so creating skinnable templates with Plates was not possible.

    One thing with Foil that keeps biting me is this line which is:

        private function doRender($path, array $data = [], $class = null)
        {
            // ...
            $output = trim($template->render($data));
            // ...
            return $output;
        }
    

    Why trim()? Can this not be left up to the developer as desired? E.g. me! Or made an option? One of things we use foil for (as well as HTML templates) is building plain text configuration files and whitespace is important here.

    Thanks, Barry.

    enhancement 
    opened by barryo 5
  • $engine->renderSection()?

    $engine->renderSection()?

    Hi, Foil seems great, i'm evaluating it for a project instead of Plates, but i can't find a way to render specific sections programmatically, also Plates does not support this, but Twig does.

    It's useful for email templates where you can have a template with 3 different sections:

    • subject
    • body_html
    • body_text

    is possible to add a function like:

    $subject = $engine->renderSection('email-template','subject-section', $some_data);
    $body_html = $engine->renderSection('email-template','body-html-section', $some_data);
    $body_text = $engine->renderSection('email-template','body-text-section', $some_data);
    

    and/or have something like:

    $tpl = $engine->getTemplate('email-template');
    $tpl->setData($some_data);
    $subject = $tpl->renderSection('subject-section');
    $body_html = $tpl->renderSection('body-html-section');
    $text_html = $tpl->renderSection('body-text-section');
    

    email-template.php:

    <?php
    $this->section('subject-section') ?>
    TEST SUBJECT
    <?php $this->stop() ?>
    <?php $this->section('body-html-section') ?>
    TEST HTML BODY
    <?php $this->stop() ?>
    <?php $this->section('body-text-section') ?>
    TEST TEXT BODY
    <?php $this->stop() ?>
    

    eventually if the requested section does not exists renderSection() will simply return null

    what do you think?

    thanks in advice!

    feature-request 
    opened by ducktype 5
  • PHP Warning:  htmlspecialchars()

    PHP Warning: htmlspecialchars()

    I see a lot of warnings after upgrading to Foil 0.4.1 :

    [Fri Apr 24 20:59:07.155292 2015] [:error] [pid 5704] [client 127.0.0.1:49545] PHP Warning: htmlspecialchars() expects parameter 1 to be string, array given in /home/bronx/www/clubman/vendor/aura/html/src/Escaper/HtmlEscaper.php on line 77

    bug 
    opened by fbraem 5
  • Question about template variables

    Question about template variables

    Hi again!

    I'm curious about the need to use $this->my_var while accessing data in templates. Is there any particular reason (performance, escaping etc.) for not using locally scoped variables like $my_var ? Plates does allow it AFAIK.

    I didn't dig into Foil that much, so my question could sound improper.

    Regards, Stoyan

    question 
    opened by skyosev 5
  • Can't render double extension templates without postfix

    Can't render double extension templates without postfix

            $engine = Foil\engine([
                'ext'     => ['tpl.php'],
                'folders' => ['path/to/templates']
            ]);
            // trying to render path/to/templates/home.tpl.php
            $engine->render('home'); 
    

    this produces

    Uncaught exception 'RuntimeException': home is not a valid template name

    Do I miss something or this is currently not possible with Foil ?

    bug 
    opened by skyosev 5
  • Nested Blocks Fail

    Nested Blocks Fail

    Hi @Giuseppe-Mazzapica ,

    I have another test case for you: https://gist.github.com/brad-jones/62985a9511836d0521b9

    Thought I would try to use Foil as a code generation tool. Works really well but then I wanted to tidy up the horrible formatting and created the "indent" block, which works great but only one level deep.

    git clone, composer install, then run these:

    • php fails.php
    • php success-not-nested.php
    bug 
    opened by brad-jones 4
  • SectionInterface::MODE_REPLACE causes child template inheritance to fail

    SectionInterface::MODE_REPLACE causes child template inheritance to fail

    Here's a simplified version of my setup:

    <!-- layout.php -->
    <html><head><etc /></head><body>
    <?php $this->section('content'); ?>
      <h1>Output some html</h1>
    <?php $this->stop();
    <?= $this->buffer() ?>
    // yadda yadda ?>
    </body></html>
    
    <!-- child.php -->
    <?php $this->layout('layout'); ?>
    <?= $this->buffer() ?>
    
    <!-- page.php -->
    <?php $this->layout('child'); ?>
    Stuff outside sections.
    <?php $this->section('content'); ?>
    Some additional stuff
    <?php $this->append(); ?>
    

    With 'section_def_mode' => Foil\Contracts\SectionInterface::MODE_REPLACE, the content section is neither appended NOR replaced. Every "referenced" section doesn't work, but other content from page.php is output correctly.

    Commenting out the MODE_REPLACE restored section inheritance into the page.

    bug 
    opened by matthew-dean 4
  • Post calls not working on PHP 7.1

    Post calls not working on PHP 7.1

    I Get 404 not found error when calling post functions as below

    PHP Deprecated: Non-static method ------ should not be called statically

    Did this packages work on PHP 7.1

    Did any updates to overcome the issue?

    opened by midhunraj 3
  • Multiple section replace don't work

    Multiple section replace don't work

    Hi Giuseppe, I've created a simple demo for, apparently, a bug I have found.

    I have a base template called: baseTemplate

    <!DOCTYPE HTML>
    <html>
    	<head>
    	</head>
        <body>
    	<? $this->section('body') ?>aaa<? $this->stop() ?>
        </body>
    </html>
    

    I have a second template called: templateA

    <? $this->layout('_layout/baseTemplate') ?>
    <? $this->section('body') ?>bbb<? $this->replace() ?>
    

    I have a third template called: templateB

    <? $this->layout('_layout/templateA') ?>
    <? $this->section('body') ?>ccc<? $this->replace() ?>
    

    While the result is supposed to be: ccc, in fact, it shows bbb

    If I change the the section ending in templateA from replace() to stop(), I get ccc.

    I would we very thankful if you could take a look at it, and fix it. :) Yoshi.

    opened by yoshkinawa 2
  • Documentation website not working

    Documentation website not working

    https://foilphp.github.io/Foil/ cannot navigate through menu, here the errors in chrome console

    Mixed Content: The page at 'https://foilphp.github.io/Foil/' was loaded over HTTPS, but requested an insecure script 'http://yandex.st/highlightjs/7.5/highlight.min.js'. This request has been blocked; the content must be served over HTTPS. theme.min.js:5 Uncaught ReferenceError: hljs is not defined at theme.min.js:5

    opened by r3verser 3
  • Development roadmap

    Development roadmap

    Hey @gmazzap. I mentioned you in another WP framework project and in connection was wondering what the status of this templating project is. Feature complete? 0.7 coming some time or too busy? Did someone else produce something even better?

    question 
    opened by lkraav 1
  • Link to blog post has no content

    Link to blog post has no content

    I got an DNS error from gm.zoomlab.it

    I suggest use this url that works: http://web.archive.org/web/20170227180224/http://gm.zoomlab.it/2015/template-engines-i-moved-from-love-to-meh-for-plates/

    opened by SlavaAurim 2
  • Duplicate code with nested sections

    Duplicate code with nested sections

    I have the following setup: The layout defines sections:

    <!DOCTYPE html>
    <html>
    <head>
        <title><?= $this->e('title') ?></title>
        <?php $this->section('head'); $this->stop(); ?>
    </head>
    <body>
    
    <?php $this->section('content');$this->stop(); ?>
    
    <?php $this->section('end-body');$this->stop(); ?>
    </body>
    </html>
    

    Then there is the template appending some content to the content section of the layout. Some of the content is loaded by including a partial:

    <?php $this->layout('layout::page', ['title' => 'Page title']) ?>
    
    <?php $this->section('content') ?>
    <h1>Test</h1>
    
    <?= $this->insert('partials::date-input'); ?>
    <?php $this->append() ?>
    

    The partial references a JS file (which should be appended to the "end-body" section of the layout) and some HTML which should be inserted whereever $this->insert('partial-name') is called.

    <?php $this->section('end-body') ?>
    <script src="/jquery.min.js"></script>
    <script src="/intercooler.js"></script>
    <?php $this->append() ?>
    
    <div ic-get-from="<url>" ic-trigger-on="scrolled-into-view"></div>
    

    The result is:

    <!DOCTYPE html>
    <html>
    <head>
        <title>Page title</title>
        </head>
    <body>
    
    <h1>Test</h1>
    
    <script src="/jquery.min.js"></script>
    <script src="/intercooler.js"></script>
    
    <div ic-get-from="<url>" ic-trigger-on="scrolled-into-view"></div>
    
    <script src="/jquery.min.js"></script>
    <script src="/intercooler.js"></script>
    </body>
    </html>
    

    So the JS files get embedded twice. I am quite sure that I did something wrong but perhaps this really is a bug.

    bug 
    opened by janwalther 3
Releases(0.6.7)
  • 0.6.7(May 4, 2017)

  • 0.6.6(May 26, 2016)

  • 0.6.5(Mar 8, 2016)

    Added

    Nothing

    Changed

    Nothing

    Fixed

    • Issue with nested blocks having callbacks that receives arguments - See #32
    • Issue when same section in replace mode is present more than once in same template - See #34
    Source code(tar.gz)
    Source code(zip)
  • 0.6.4(Feb 22, 2016)

    Added

    Nothing

    Changed

    • Template object has dependency to section factory and not to sections. No API change.

    Fixed

    • supply() issue when same engine instance is used more than once (see #31)
    • SectionInterface::MODE_REPLACE causes template inheritance to fail (see #30)
    Source code(tar.gz)
    Source code(zip)
  • 0.6.3(Nov 1, 2015)

  • 0.6.2(Jul 6, 2015)

  • 0.6.1(Jul 4, 2015)

  • 0.6.0(Jul 3, 2015)

    New Features, Issues Solved

    • Introduced Blocks and Custom Blocks feature
    • Introduced "alias" feature that shorten syntax to access variables and functions inside templates
    • Introduced Section Rendering feature
    • Better control on registered folders, see docs.
    • Engine::render(), Engine::find() and Finder::find() now also accepts an array of template names to be searched in registered folders. The first found is returned.
    • Introduced Foil\Foil class
    • Fixed issue on arraization of objects
    • Clean up & code style improvements

    Backward Compatibility Breaks

    • Foil\API class has been removed
    • Foil\Contracts\APIAwareInterface has been removed
    • Foil\Traits\APIAwareTrait has been removed
    • Foil\Bootstrapper class has been removed
    • Most of the API functions have been removed. See docs.
    • Foil\engine() functions now always returns a "fresh" instance of Foil\Engine class, whereas in older versions always returned same instance when called more times.
    Source code(tar.gz)
    Source code(zip)
  • 0.5.1(May 25, 2015)

  • 0.5.0(May 25, 2015)

    Easing the process of using custom template classes.

    • private methods in Template class have been changed to protected
    • introduced 'template_class' engine option
    • add a third argument, $class, for the Engine::renderTemplate() method
    Source code(tar.gz)
    Source code(zip)
  • 0.4.3(May 22, 2015)

  • 0.4.2(Apr 24, 2015)

  • 0.4.0(Apr 22, 2015)

    • Introducing support for Aura.HTML for escape (and autoescape)
    • Added Aura.HTML extension for HTML and Form helpers
    • Added docs for new features
    • Added new Escaper class (and interface) that makes use of Aura.HTML escaper
    • New options 'default_charset' and 'html_tags_functions'
    • Improved phpDoc
    • Minor bug & CS fix
    Source code(tar.gz)
    Source code(zip)
  • 0.3.0(Mar 18, 2015)

    • supply() template method now supports a callback as default value
    • added support for 'strict_variables' engine option to throw an exception or a notice when using undefined vars
    • updated documentation
    • various typo and CS fixes
    Source code(tar.gz)
    Source code(zip)
  • 0.2.0(Feb 18, 2015)

    • Added insertIf() template tag to insert partial conditionally
    • layout() now accepts also full path of layout
    • some minor internal improvements
    • updated docs (and site) for new feaures
    Source code(tar.gz)
    Source code(zip)
  • 0.1.4(Jan 25, 2015)

  • 0.1.3(Jan 21, 2015)

  • 0.1.2(Jan 21, 2015)

Owner
Foil PHP
A PHP Template Engine, for PHP templates.
Foil PHP
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 174 Nov 12, 2022
SilverStripe live templates - Speed up development with SilverStripe live templates for PhpStorm and WebStorm

SilverStripe live templates My collection of live templates for WebStorm and PhpStorm, following PSR-2, using PHPDoc, and utilizing PHP 5.4 array shor

North Creation Agency 3 Feb 1, 2022
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 Dec 3, 2022
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 123 Aug 15, 2022
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 2k Dec 1, 2022
☕ 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 891 Dec 2, 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.

刘小乐 142 Oct 19, 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 18 Sep 26, 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
Pug (Jade) template engine for Symfony

Pug-Symfony Pug template engine for Symfony This is the documentation for the ongoing version 3.0. Click here to load the documentation for 2.8 Instal

Pug PHP 41 Oct 21, 2022
PHPlater, a simple template engine.

PHPlater A simple PHP template engine that lets PHP do all the logic and then append it to the HTML in the template file. It is set to solve the probl

John Larsen 2 Jun 3, 2022
A template abstraction prototype for PHP template engines

Schranz Templating A template abstraction prototype for PHP template engines. This project should help to find a way for a general Template Render Int

Schranz Templating 13 Nov 19, 2022
Qiq templates for PHP 8.

Qiq Templates for PHP 8 This package provides a PHP 8.0 implementation of the TemplateView and TwoStepView patterns using PHP itself as the templating

null 18 Nov 24, 2022
Simple PHP templating system for user editable templates.

Simple template Simple PHP templating system for user editable templates. Idea Most applications need to render templates that insert safely treated v

Baraja packages 1 Jan 23, 2022
Contao extension to provide content templates for pages.

Contao Content Templates In Contao, the regular content of a page can be made up of different articles, each assigned to different sections of a page

inspiredminds 7 Oct 11, 2022
Renders Mithril components to HTML for use in blade templates

Flarum Mithril2Html Uses Chrome Puppeteer via Spatie Browsershot to render Mithril components as static HTML. Follow Browsershot instructions to setup

Clark Winkelmann 3 Nov 13, 2022
Laravel Live Templates for PhpStorm

Laravel Live Templates for PhpStorm How to: Go to Preferences | Tools | Settings Repository Add Read-only Source https://github.com/koomai/phpstorm-la

Sid 1.2k Nov 2, 2022
Yii2 Gii Extended templates and generators

model template with TimestampBehavior and BlameableBehavior according to columns

潘文斌 1 Feb 12, 2020