Drupal 8 8.0.2
Overview of the Theme system and Render API.
The main purpose of Drupal's Theme system is to give themes complete control over the appearance of the site, which includes the markup returned from HTTP requests and the CSS files used to style that markup. In order to ensure that a theme can completely customize the markup, module developers should avoid directly writing HTML markup for pages, blocks, and other user-visible output in their modules, and instead return structured "render arrays" (see Render arrays below). Doing this also increases usability, by ensuring that the markup used for similar functionality on different areas of the site is the same, which gives users fewer user interface patterns to learn.
For further information on the Theme and Render APIs, see:
The core structure of the Render API is the render array, which is a hierarchical associative array containing data to be rendered and properties describing how the data should be rendered. A render array that is returned by a function to specify markup to be sent to the web browser or other services will eventually be rendered by a call to drupal_render(), which will recurse through the render array hierarchy if appropriate, making calls into the theme system to do the actual rendering. If a function or method actually needs to return rendered output rather than a render array, the best practice would be to create a render array, render it by calling drupal_render(), and return that result, rather than writing the markup directly. See the documentation of drupal_render() for more details of the rendering process.
Each level in the hierarchy of a render array (including the outermost array) has one or more array elements. Array elements whose names start with '#' are known as "properties", and the array elements with other names are "children" (constituting the next level of the hierarchy); the names of children are flexible, while property names are specific to the Render API and the particular type of data being rendered. A special case of render arrays is a form array, which specifies the form elements for an HTML form; see the Form generation topic for more information on forms.
Render arrays (at each level in the hierarchy) will usually have one of the following three properties defined:
#allowed_tags: If #markup is supplied this can be used to change which tags are using to filter the markup. The value should be an array of tags that Xss::filter() would accept. If #plain_text is set this value is ignored.
Render elements are defined by Drupal core and modules. The primary way to define a render element is to create a render element plugin. There are two types of render element plugins:
Modules can define render elements by defining an element plugin.
The Drupal rendering process has the ability to cache rendered output at any level in a render array hierarchy. This allows expensive calculations to be done infrequently, and speeds up page loading. See the Cache API topic for general information about the cache system.
In order to make caching possible, the following information needs to be present:
Cache information is provided in the #cache property in a render array. In this property, always supply the cache contexts, tags, and max-age if a render array varies by context, depends on some modifiable data, or depends on information that's only valid for a limited time, respectively. Cache keys should only be set on the portions of a render array that should be cached. Contexts are automatically replaced with the value for the current request (e.g. the current language) and combined with the keys to form a cache ID. The cache contexts, tags, and max-age will be propagated up the render array hierarchy to determine cacheability for containing render array sections.
Here's an example of what a #cache property might contain:
At the response level, you'll see X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags headers.
See https://www.drupal.org/developing/api/8/render/arrays/cacheability for details.
The #attached property can also be used to specify HTTP headers and the response status code.
See for additional information.
See ::parseLibraryInfo() for more information on how to define libraries.
Render arrays have a placeholder mechanism, which can be used to add data into the render array late in the rendering process. This works in a similar manner to ::placeholderFormat(), with the text that ends up in the #markup property of the element at the end of the rendering process getting substitutions from placeholders that are stored in the 'placeholders' element of the #attached property.
For example, after the rest of the rendering process was done, if your render array contained:
then #markup would end up containing 'Something about replacement'.
Note that each placeholder value can itself be a render array, which will be rendered, and any cache tags generated during rendering will be added to the cache tags for the markup.
The term "render pipeline" refers to the process Drupal uses to take information provided by modules and render it into a response. See https://www.drupal.org/developing/api/8/render for more details on this process. For background on routing concepts, see Routing API.
There are in fact multiple render pipelines:
Routes whose controllers return a object are fully handled by the Symfony render pipeline.
Routes whose controllers return the "main content" as a render array can be requested in multiple formats (HTML, JSON, etc.) and/or in a "decorated" manner, as described above.