Skip to content
Create a gist now

Instantly share code, notes, and snippets.

Embed URL


Subversion checkout URL

You can clone with
Download ZIP
PHP Templating Engine with bindable $this support in 53 LOC

Template Class, with support for binding object contexts to the template.

Requires PHP 5.4 for Closure $this support


Put this in a file named composer.json:

    "repositories": [
        {"type": "vcs", "url": "git://"}
    "require": {
        "chh/simple-template": "*"

Get Composer and install:

php composer.phar install



Hello World <?= $name ?>
Here is the output of some method: <?= $this->foo() ?>
Here is the value of a context property: <?= $this->bar ?>

Template Controller


require "Template.php";

use CHH\Template;

class Context
  var $bar = "Some Context Property";

  function foo()
    return "Context::foo()";

$template = new Template('/hello_world.phtml');
echo $template->render(new Context, ['name' => 'Jim']);

This yields:

Hello World Jim
Here is the output of some method: Context::foo()
Here is the value of a context property: Some Context Property
"name": "chh/simple-template",
"description": "Minimal template class, using Closure Object Binding.",
"authors": [
{ "name": "Christoph Hochstrasser", "email": "" }
"require": {
"php": ">=5.4.0"
"autoload": {
"classmap": ["."]
namespace CHH;
class SimpleTemplate
protected $file;
function __construct($file)
if (!is_file($file) or !is_readable($file)) {
throw new \InvalidArgumentException(
"File $file does not exist or is not readable"
$this->file = $file;
# Renders the template
# context - Is the object to which $this inside
# the template refers to.
# vars - Is an array of key-value pairs, which are
# available within the template as local variables.
# Returns the rendered template as String.
function render($context = null, array $locals = [])
if (null === $context) {
$context = new \StdClass;
} else if (is_object($context)) {
$context = clone $context;
} else {
throw new \InvalidArgumentException("Invalid Context given. Context must be an object");
# Create the sandbox for the template to execute in
$template = function($__file__, array $__locals__ = array()) {
// Set all keys in $__locals__ as local variables
foreach ((array) $__locals__ as $var => $value) {
$$var = $value;
unset($var, $value, $__locals__);
include $__file__;
return ob_get_clean();
# Bind $this inside the closure to the context object
$template = $template->bindTo($context);
return $template($this->file, $locals);

Any thoughts on how you prevent views from accessing the private vars and methods?


Specifically the protected $bar of the context. I love the idea of transferring the entire context object instead of manually assigning context vars, but re-assigning $this and giving access to protected vars and methods seems like it should be avoided.

CHH commented

You're right, that should be avoided.

Actually it doesn't have any access to the $bar property. I've messed up with the example code.

I've checked it with 5.4.0beta2 and they now changed the default scoping behaviour of bindTo, so closures don't have access to protected and private class members by default. Actually if you try the example it throws an fatal error, with the reason that the protected property $bar could not be accessed.

So I've fixed the example code by making the bar property public.

Thanks for pointing this out!



I guess in SimpleTemplate.php we can replace the lines from 41-44 with


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.