Magic Methods

Justin Hileman edited this page Apr 15, 2014 · 4 revisions

Mustache.php supports PHP magic methods. Specifically, it supports:

  • __toString
  • __isset and __get
  • __invoke


Whenever an object or value is interpolated in Mustache, it is coerced into a string. This means, if you want to have control over how your object shows up inside {{ myInstance }} tags, you'll want to implement the __toString method.

Note that you must return a string from __toString. If you return anything else, you'll get anything from an error message in the middle of your template, to a PHP warning, to a full blown meltdown, depending on your current PHP settings.

__isset and __get

These two come in pairs. If you want to use __get magic accessors inside Mustache, you must implement __isset as well. This is just good practice, in general, but it's essential for Mustache to prevent objects from masking other properties and objects higher on the context stack.


In PHP 5.3 or newer, objects which implement __invoke are considered "callable", and can be used as higher-order sections.

Note that __call is missing

Unfortunately, PHP lacks an equivalent to __isset for __call. Short of trying to call a method on an object, there is no way to tell whether it will handle the call. This is fundamentally incompatible with the Mustache context stack. Take this, for example:

{{# foo }}{{ label }}: {{ name }}{{/ foo }}

And the ViewModel:

class Foo {
    public $name;
    public function __call($method, $args) {
        return 'unknown value';

And the data:

$foo = new Foo;
$foo->name = 'Bob';
  'label' => 'name',
  'foo'   => $foo,

This will render as:

unknown value: unknown value

This is because inside the {{# foo }} section, the __call method on Foo would mask the {{ label }} lookup higher in the context stack, returning unknown value instead of name. Because methods win over properties, it would even do the same for Bob's $name property. This is obviously not what you would expect.

The good news is that you can use __isset and __get instead, just like you would normally use __call :)