understanding drupal 7's render array api

drupal's render API provides great flexibility for themers and module developers to change the rendering of page, and it is the fundamental element of a drupal page rendering.
as the name implies, it is just an associative php array with predefined elements and data structure that conforms to drupal's theme system.
It took me some time to understand how the render APi actually work.Here i want to share my experience in learning about drupal render api with a simple module.

Create a drupal module

First of all, let's create 2 files under sites/all/modules/:

render_array.info
render_array.module

the contents of render_array.info will be

name = render array
description = understanding drupal's render api
package = test modules
core = 7.x

Implement a hook menu function

then in the render_array.module, we paste the followng code to implement hook_menu function so we have a page to test

<?php
function render_array_menu() {

$items['testpage'] = array (
               'title' => 'learning render array',
               'page callback' => 'learning_render_array',
               'access callback' => TRUE,
       );

   return $items;
}

we set the callback function to learning_render_array.When we visit yoursite.com/testpage,learning_render_array will be called to generate the html

a simple render array that is used to return the html string will be something like this:

function learning_render_array() {

           $render_array['myrender_array'] = array (
                            '#markup' =>'<p>this is a test</p>',
                             );
       return $render_array;
}

for the sake of learning, we change the function to:

function learning_render_array() {

      $render_array['myrender_array'] array(
               'output' => t('<p>this is the main content, outputted by #theme</p>'),
               '#note' => t('<p style="background-color:green">this is generated by out custom render array property #note</p>'),
               '#pre_render' => array('add_heading_to_output'),
               '#theme' => 'output_render_array',//theme function
               '#theme_wrappers' => array ('render_array_wrapper'),//theme wrapper function       
               '#post_render' => array('add_footnote_to_output'),
          ),);
    return $render_array;
}

This just look like an ordinary associative php array, apart from the # symble prefixing for some elements, which will provides hints to drupal on how to render a page.
we will have a look at these elements one by one.

the outer array key is just a random one that you can define youself, so is the inner key 'output' and '#note'.

i'd like to focus more on the last 4 properties, #theme, #theme_wrappers,#pre_render,#post_render.

#theme,

when this key is set, drupal will pass the responsibility of how to render this data to the function.Please note the actual function to be called will be one prefixed with
theme_, namely theme_output_render_array, which needs to be registered with a theme hook.

function render_array_theme() {
  $items = array(
    'output_render_array' => array(
      'render element' => 'element',
    ),
   
    'render_array_wrapper' => array(
      'render element' => 'element',
    ),
  );
  return $items;
}

theme_output_render_array will get the array data in the form of $vars['element'].the key is 'element' because we set 'render element' = 'element' in the theme hook function. you can use whatever key name you like.

here is the contents of theme_output_render_array:

function theme_output_render_array($variables) {

            $output = '';
            $output .= $variables['element']['output'].$variables['element']['#note'];
           
            return $output;
}

We concatenate the element the value of element 'output' and '#note' into single string and return it to drupal render API for further processing;

if the other 3 elements are not set, this will be final output.

'#pre_render'

actually '#pre_render' function is called before #theme gets called;its job is to alter data in the array not html string and it gets one parameter,the whole array.

function add_heading_to_output($element) {

         $element['output'] = t('<p style="background-color:yellow;">this heading is generated by #pre_render</p>').$element['output'];
          return $element;
       
}

this function modify the value of the 'output' element, you can also make other changes to the elements.

#theme_wrappers

This is an array of theme hooks just like #theme, and it will be called after all children elements have been rendered and html string is added to #children element.in most cases, it is used to add outer div wrapper to already rendered children element.And it is rarely used with #theme.

function theme_render_array_wrapper($variables) {

           $output = '<div style="border:1px solid red">';
           $output .= $variables['element']['#children'];
           $output .= '</div>';
      return $output;
}

<h3>'#post_render'</h3>

'#post_render' get access to 2 variables, the rendered content and the original render array.
  function add_footnote_to_output($markup,$element) {

        $markup = $markup.t('<p style="background-color:blue;">this is added by #post_render element</p>');
       
        return $markup;
       
     }

Tags: