Renderers for application developers
You are an application developer? Here is what you need to know to use the rendering system efficiently.
The rendering system provides an easy way to render in HTML your objects. This is a 3 steps process:
- Your class should implement the
HtmlElementInterface
(optional) - Your class should use the
Renderable
trait - You should add a template file in the src/templates directory
Then you can render your class using the toHtml()
method provided by the Renderable
trait.
Here is a minimalistic sample:
namespace MyNamespace;
use Mouf\Html\HtmlElement\HtmlElementInterface;
use Mouf\Html\Renderer\Renderable;
// My class implements the HtmlElementInterface interface
class MyClass implements HtmlElementInterface {
// My class uses the Renderable trait
use Renderable;
public $myValue;
}
Now, I need to provide a template file. The template file should be named after the PSR-0 convention and placed in the src/templates directory. It can have the ".php" or ".twig" extension.
In this example, if we are using Twig as a templating engine, the file name should be src/templates/MyNamespace/MyClass.twig
<h1>Sample class</h1>
{{ this.myValue }}
We could also use the PHP templating engine. In that case, the file name would
be src/templates/MyNamespace/MyClass.php
<h1>Sample class</h1>
<?php echo $object->myValue ?>
About Twig templates
Twig is a templating engine for PHP. The main reason to use Twig is that Twig automatically protects you from XSS by escaping HTML strings (unless you tell it not to espace the string). It has also a very concise syntax making it pleasant to use.
When you are working with Twig, your object is accessible using the "this" variable.
In your class | In Twig |
---|---|
public $myVar |
{{ this.myVar }} or {{ myVar }} (public properties can be accessed without the this keyword. |
public function getVar2() { ... } |
{{ this.var2 }} or {{ this.getVar2 }} |
Please note you cannot access protected or private properties.
Autoescaping is enabled by default. Performance-wise, templates are compiled as PHP files and cached. When a template file is modified, Twig detects the change and recompiles the template.
Twig extensions
The rendering engines comes with a set of functions dedicated to Mouf. For instance, you can
use the toHtml()
Twig function to render any widget declared as a Mouf instance. You can use
val()
Twig function to evaluate any instance implementing ValueInterface
.
You can check all these function and more on the
Mouf's Twig extensions page.
About PHP templates
Plain PHP files can also be used as template files. This is way more flexible than Twig, but there are also way more ways to make errors. The $object variable is a pointer to the object you are rendering.
In your class | In your PHP template |
---|---|
public $myVar |
<?= $myVar ?> or <?= $object->myVar ?> (public properties can be accessed as variables without using the $object variable. |
public function getVar2() { ... } |
<?= $object->getVar2() ?> You can access any method of the object through the $object variable. |
Calling the renderer
To call the renderer, you just have to call the toHtml()
method.
Here is a sample:
use MyNamespace\MyClass;
$myObject = new MyClass();
$myObject->myValue = 42;
$myObject->toHtml();
So this is very easy.
One thing that is important to note: if your class
implements the HtmlElementInterface
class
(and you can implement it because all necessary methods are provided by the Traversable
trait),
then you can use instances of your class in many packages provided by Mouf (especially, you can drag'n'drop
instances if your class directly into blocks, that are used by templates). This can be very useful!
Extending existing renderers
Some packages or templates you are using might also be using renderers. The great news is that you can overload these renderers with your own renderers very easily.
Let's take a sample. The mouf/html.widgets.messageservice package provides a Mouf\Html\Widgets\MessageService\Widget\RenderedMessage class that is "renderable". It represents a warning/error/info message displayed usually at the top of the screen. Want to change the markup of that message? Easy! Just create your own renderer in src/template/Mouf/Html/Widgets/MessageService/Widget/RenderedMessage.twig.
For instance:
<div class='alert alert-{{ this.userMessage.type|e('html_attr') }}'>
{{ this.userMessage.message|raw }}
{% if this.nbMessages > 1 %}
<strong>x {{ this.nbMessages }}</strong>
{% endif %}
</div>
Under the hood
You might be interested in knowning what is exactly happening when you call the "toHtml()" method of your object.
Here is what is happening:
- The render method of the default renderer is called, and your object is passed to it.
- What is the default renderer? It is a Mouf instance whose name is "defaultRenderer"
- What is the default renderer doing? It will chain all the renderers it can find in Mouf, in this order:
- First, it will look at the developer renderers (by default in the "src/template" directory)
- Then, if a template has been used, it will look at the template's renderers to find a match
- Finally, it will try to find a template in the packages installed. A package can also have a renderer. Renderers in the packages can be ordered by priority.
Now that we saw how an application developer can use and overload a package template, let's have a look at the way things are done on the package developer side
Found a typo? Something is wrong in this documentation? Just fork and edit it!