Magic Methods - bobthecow/mustache.php GitHub Wiki
Mustache.php supports PHP magic methods. Specifically, it supports:
__toString
__isset
and__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
In PHP 5.3 or newer, objects which implement __invoke
are considered "callable", and can be used as higher-order sections.
__call
is missing
Note that 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(array(
'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
:)