Render API

Two parts:
Render pipeline
Render arrays
Render Arrays
- builduing blocks of a Drupal page
- structured arrays
- kept as arrays until the final stage of generating the response
Render arrays are nested and thus form a tree. Consider them Drupal's "render tree" — Drupal's equivalent of the DOM.
What is "rendering" ?
Turning "render" arrays into HTML
What is a render array ?
A structured array that provides data along with hints as to how it should be rendered
$page = [
'#type' => 'page',
'content' => [
'system_main' => […],
'another_block' => […],
'#sorted' => TRUE,
),
'sidebar_first' => [
…
],
];A page render array
$example = [
'#prefix' => '<div class="hello">',
'#markup' => 'Hello world!,
'#suffix' => '</div>',
];<div class="hello">Hello world!</div>Example
Render array properties
#type
Set of predefined properties
$example = [
'link' =>
'#title' => t('Homepage'),
'#type' => 'link',
'#url' => Url::fromRoute('<front>'),
],
];<a href='/'>Homepage</a>#cache
Very flexible cacheability
#markup
Provides HTML markup directly
If it is too complicated please use #theme or #type instead.
Strips XSS vectors
<a href='/'>Homepage</a>
Welcome to my awesome site !$example = [
'link' => [
'#title' => t('Homepage'),
'#type' => 'link',
'#url' => Url::fromRoute('<front>'),
],
'slogan' => [
'#markup' => t('Welcome to my awesome site !'),
],
];#prefix
#suffix
$example = [
'link' => [
'#title' => t('Homepage'),
'#type' => 'link',
'#url' => Url::fromRoute('<front>'),
],
'slogan' => [
'#prefix' => '<h2>',
'#markup' => t('Welcome to my awesome site !'),
'#suffix => '</h2>',
],
];<a href='/'>Homepage</a>
<h2>Welcome to my awesome site !</h2>#pre_render
Alters the array before it is rendered
$example = [
'link' => [
'#title' => t('Homepage'),
'#type' => 'link',
'#url' => Url::fromRoute('<front>'),
],
'slogan' => [
'#prefix' => '<h2>',
'#markup' => t('Welcome to my awesome site !'),
'#suffix => '</h2>',
'#pre_render' => array('MyRenderer', 'replaceH2withH3'),
],
];class MyRenderer {
public function replaceH2withH3(array &$build) {
$build['#prefix'] = '<h3>';
$build['#suffix'] = '</h3>';
}<a href='/'>Homepage</a>
<h3>Welcome to my awesome site !</h3>#post_render
Alters the array after it is rendered
$example = [
'link' => [
'#title' => t('Homepage'),
'#type' => 'link',
'#url' => Url::fromRoute('<front>'),
],
'slogan' => [
'#prefix' => '<h2>',
'#markup' => t('Welcome to my awesome site !'),
'#suffix => '</h2>',
'#pre_render' => array('MyRenderer', 'replaceH2withH3'),
'#post_render'=> array('MyRenderer', 'addDivWrapper'),
],
];class MyRenderer {
...
public function addDivWrapper(array $build, &$output) {
$output = '<div>' . $output . '</div>';
}<a href='/'>Homepage</a>
<div><h3>Welcome to my awesome site !</h3></div>#theme
Takes responsibility of rendering
Knows the structure of the array
$example = [
...
'greeting' => [
'#theme' => 'my_awesome_array',
'#name'=> \Drupal::currentUser()->getUsername(),
],
];function hook_theme($existing, $type, $theme, $path) {
return [
'my_awesome_array' => [
'variables' => [
'name' => NULL
],
],
];
}<a href='/'>Homepage</a>
<div class="slogan"><h3>Welcome to my awesome site !</h3></div>'
<div class='greeting'>Hello Daniel !</div>/** my-awesome-array.html.twig */
<div class='greeting'>Hello {{ name }} !</div>#theme_wrappers
Mostly adds wrappers to rendered children
$example = [
...
'#slogan' => [
'#theme_wrappers' =>[
'container' => [
'#attributes' =>
'#class' => 'slogan',
],
],
...
],
];<a href='/'>Homepage</a>
<div class="slogan"><h3>Welcome to my awesome site !</h3></div>
<div class='greeting'>Hello Daniel !</div>$example = [
'link' => [
'#title' => t('Homepage'),
'#type' => 'link',
'#url' => Url::fromRoute('<front>'),
],
'slogan' => [
'#prefix' => '<h2>',
'#markup' => t('Welcome to my awesome site !'),
'#suffix => '</h2>',
'#pre_render' => array('MyRenderer', 'replaceH2withH3'),
'#post_render'=> array('MyRenderer', 'addDivWrapper'),
'#theme_wrappers' =>[
'container' => [
'#attributes' =>
'#class' => 'slogan',
],
],
],
'greeting' => [
'#theme' => 'my_awesome_array',
'#name'=> \Drupal::currentUser()->getUsername(),
],
];<a href='/'>Homepage</a>
<div class="slogan"><h3>Welcome to my awesome site !</h3></div>
<div class='greeting'>Hello Daniel !</div>Finally
For more check
Some elements could be unavailable for Render API, but it is the best documentation we got.
Why ?
Flexibility
Cacheability
How are render arrays related to element types ?
Modules can define new RenderElement plugins.
/**
* @RenderElement("fieldset")
*/
class Fieldset extends RenderElement {
/**
* {@inheritdoc}
*/
public function getInfo() {
$class = get_class($this);
return array(
'#process' => array(
array($class, 'processGroup'),
array($class, 'processAjaxForm'),
),
'#pre_render' => array(
array($class, 'preRenderGroup'),
),
'#value' => NULL,
'#theme_wrappers' => array('fieldset'),
);
}
}
Render Pipeline
Render API
By Popdan Daniel
Render API
- 651