Reflecting on PHPTI

PHPTI (PHP Template Inheritance) was a fun project to work on, but it’s easy to see, by looking at the commit log, that I stopped maintaining it a while ago. In this blog post, I want to officially announce PHPTI as “no longer maintained” and also reflect on its successes and failures.
First off, I still strongly believe in the concept of template inheritance and feel it is a powerful ally while coding reusable HTML layouts. It makes everything so elegant. A sub-template defines which template it wants to inherit from, and no controllers or other layers need to intervene.

I was first introduces to template inheritance by Django’s templating engine. With PHPTI, I wanted to make a similarly elegant implementation, only in PHP code, where PHP was the template engine itself. I think I succeeded in coming up with a minimal syntax (with short_open_tag, that is) but I was forever bound to PHP’s parser and request lifecycle. Herein lies PHPTI’s greatest strength and greatest weakness.

I wanted all template blocks defined in a single file. Having them in separate files, which is how CakePHP implemented template inheritance (and maybe still does), was not an option for me. Also, I wanted the template to execute in the caller’s scope (usually the global scope) so that the template “variables” could simply be PHP variables that were set beforehand. The only way to satisfy these requirements was through the use of output buffers.

The output buffer implementation proved to be a little awkward to the end-developer. First off, the developer has to realize that all of their blocks will be executed, even when an overridden block’s contents will be thrown away. Also, it was unfortunate but necessary to expose certain buffer-related hooks like flushblocks and blockbase.

Also, there seemed to be a little contention around how PHPTI’s API was exposed. I chose to use global functions like startblock/endblock because minimal-looking code was the highest priority to me. Others would have preferred to use static class functions or object methods of a global. PHP 5.3 introduced namespaces, but importing all the functions manually at the top of each template file seemed like unsightly boilerplate. In summary, I couldn’t really find a solution that pleased everyone (or even most people).

All these little warts made me slowly realize that PHP was not the best medium to implement template inheritance in. Was a 3rd-party non-PHP template language the better alternative? Traditionally, I had been a PHP purist in this regard. I liked that no additional language needed to be learnt and no context switching needed to take place. I also liked that you got PHP’s standard library, most importantly the string functions, for free.

However, I’ve recently been a convert to the opposite camp. There are just too many downsides to the straight-PHP approach. Escaping input is inconvenient (and more importantly, not default behavior). There is no way to prevent “logic” from creeping into the template layer. And most relevant to us, you can’t extend the language to do cool things cleanly, like template inheritance.

Also, there is a growing need to implement templating on the client side, in JavaScript. This makes the PHP templating issue a moot point in my opinion. Having one unified template language on your client and server is a huge win. The hot one right now is Mustache, which comes in PHP, JavaScript, and a variety of other languages. However, neither Mustache nor it’s cousin Handlebars supports template inheritance.

It seems that Mustache is toying with the idea of template inheritance. It seems that Hogan (a Mustache derivative) has already implemented it, but still needs to document it. However, there have been no developments on the PHP Mustache front. If you are a template inheritance enthusiast and want to contribute to open-source, this seems like the place to start! Another possibility might be porting one of the more popular PHP template engines (like Twig) over to JavaScript.

Anyways, when thinking about PHPTI’s future, these were the internal conversations I had. But this doesn’t have to be the end. If you have any inquiries about continuing PHPTI’s development in any way, shape, or form, please contact me. In the meantime, I will be focusing my attention on other open source projects, namely FullCalendar.

  • Jim

    I hear you. But you just have to enjoy PHPTI. I haven’t found anything as simple or a model where inheritance just works how I want it to work. Suggestions or how I would proceed:
    First: combine some ideas about template variable safety (for front end developers) which I first learned about here http://codeangel.org/articles/simple-php-template-engine.html
    Second: turn to PHPTI into a class for scope reasons and to hide buffer stuff.
    In essence create a lightweight drop-in View component for MVC-like systems. structure.

  • Munawwar

    Client-side templating is great, but for SEO reasons, server-side templating is still useful. And it doesn’t have to be the same library/syntax as the client-side one, because template inheritance is still helpful in keep template content separated from ‘page content’. Hence a mix of phpti+mustache seems to be attractive (for small websites phpti is sufficient actually).

    About logic creeping into template layer: I believe templating isn’t 100% logic-less. You still need ‘if’s and loops..however the logic you write is only for the purpose of rendering the view/partial view. I’ve needed to add logic for rendering menu that has page specific css (I could have achieved the same with a client-side solution..but whatever). The logic just needed to be moved elsewhere (like to a function in a different file) and called from the template. It keeps the template cleaner. (Also possible to go with a MVC solution like Jim suggested)

  • Hi there,
    stumgbled on the phpti project looking for a way to incorporate
    template inheritance for a multi-purpose template i am working on

    here:

    https://github.com/foo123/Contemplate

    The engne supports PHP-like templating for PHP, client-side js and nodejs, with caching, include directives and template directives

    i was thinking of adding inherittance as well, without going to a full parser. i think that a way around it will be found.

    Any ideas welcome.

    PS Twig has already been ported to nodejs as swig, but the idea behind contemplate is to use php-like syntax and NOT a full-fledged parser
    (for performance reasons and not learn another syntax)