Magic methods - bobthecow/mustache.php GitHub Wiki
Mustache.php supports PHP magic methods. Specifically, it supports:
__toString__issetand__get__invoke
__toString
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.
__invoke
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:
<?php
class Foo {
public $name;
public function __call($method, $args) {
return 'unknown value';
}
}
And the data:
<?php
$foo = new Foo;
$foo->name = 'Bob';
$tpl->render([
'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 :)