Using the Render API

What Is a Render Array? 

Many of the variables in template files are straightforward, but you’ll notice that some of the variables are printed along with a function called render(). Render arrays are structured arrays that contain nested data and other information needed by Drupal to turn them into HTML using Drupal’s Render API. Variables that are render arrays are generally easy to spot in template files because they are printed using a function called render().  php

In page.tpl.php, you’ll notice that all of the regions are printed using the render() function. Each region is an element (another array) nested inside the $page array. The code in Listing 16–13 is all that’s needed to render each region. Each render() call returns fully formatted HTML for all the contents of the render array.  html

<?php print render($page['sidebar_first']); ?>



To find out what’s inside this array, use the dpm() function provided with the Devel module to print it inside of page.tpl.php: <?php dpm($page['sidebar_first']); ?>. As you can see in Figure 16–4, there are two top-level render elements inside this array, the Search form block and the Navigation block, which are currently printing in the first sidebar. 



Identifying Render Elements

An easy way to identify arrays as render elements is the presence of properties. Render elements are always arrays, and they always contain properties that always begin with a hash tag. In Figure 16–4, you can immediately tell that $page['sidebar_first'] is a render element because it contains a few properties: #sorted, #theme_wrappers, and #region. These properties are used by drupal_render() which is called when using drupal_render() to determine how to render the output. For details about drupal_render() see http://api.drupal.org/api/function/render/7. 
As themers, you won’t be getting deep into the more developer-centric properties, but there are a few that will be helpful for you to make sense of out what these arrays mean. These are described in Table 16–1. 
node

属性 描述
#theme 
Specifies the theme hook, which can be either a function or a template to use when rendering the element. 
#theme_wrappers
An array containing theme hook(s) to be used to wrap the rendered children of 
the element. For example, when theming a block, the #theme property would be
block and the #theme_wrappers property would contain region. This ensures 
that after the block(s) are rendered, the children would be run through the 
region template as well. 
#type 
The type of element that will be rendered. The default properties for element 
types are defined in hook_element_info() implementations. 
#prefix & #suffix 
A string containing markup to be placed before (prefix) or after (suffix) the 
rendered element. 
#weight 
A number that is used to sort the elements to determine the order in which they 
will print. 
#sorted
A Boolean (TRUE or FALSE) that indicates whether or not the children have been
sorted. For example, this is used in conjunction with the #weight property to 
sort the blocks in a region. When reordering blocks in a theme via 
hook_page_alter(), you'll need to specify #sorted => FALSE in addition to the 
#weight to trigger a new sort when you need to move a block to any other 
position than below the already sorted elements. 
#attached 
The #attached property is used to specify corresponding CSS, JavaScript, or 
libraries to load when the element is rendered. 
See the documentation at http://api.drupal.org/api/function/drupal_render/7 for more information.

Manipulating the Output of Render Elements 

As mentioned, having a structured array to work with is far more flexible than a bunch of HTML. This allows you to make only the changes you want to make with ease, whether big or small, without having to re-write code from scratch.  api

The prospect of using render arrays to generate markup and using alter hooks in general are 
completely new concepts to Drupal theme developers. It’s very different than what you are used to, in a good way, but it takes some getting used to. In a lot of ways it’s easier than creating templates and theme functions for one-off implementations. The biggest issues front-end developers face when using the 
Render API are: 
1.  Thinking about generating markup differently. 
2.  Figuring out how to modify the content of a render array. 
3.  Getting comfortable with implementing alter hooks. 
Unlike theme hooks, render arrays are modified using alter hooks, not preprocess functions and 
templates. This can be confusing at first because render arrays are similar to theme hooks in that their purpose is to ultimately generate HTML markup, and they use templates and theme functions to do so.  app

With render arrays, the #theme property, which allows you to define which theme function or template should be used to render the element, is just one of many properties used and can be changed at any time.  In general, you’ll use templates and theme functions to modify the markup itself, and you’ll use alter hooks to modify contents, structure, or placement of the elements before it’s rendered.  The following sections contain a few examples of things you can do with render arrays. 
ide

Generate New Content on the Fly 

Generating new content is as simple as adding a new element to the page array. Listing 16–14 shows the addition of a new element called “new_stuff” to the pre-existing Highlighted region by implementing hook_page_alter() in a theme’s template.php.  flex

<?php 
/** 
* Implements hook_page_alter(). 
*/ 
function mytheme_page_alter(&$page) { 
  $page['highlighted']['new_stuff'] = array( 
    '#type' => 'container', //这里会使用theme_container render它
    '#attributes' => array('class' => 'my-container'), 
  ); 
  $page['highlighted']['new_stuff']['heading'] = array( 
    '#type' => 'html_tag', 
    '#tag' => 'h2', 
    '#value' => t('Heading'), 
    '#attributes' => array('id' => 'my-heading'), 
  ); 
  $page['highlighted']['new_stuff']['list'] = array( 
    '#theme' => 'item_list', 
    '#items' => array( 
      'First item', 
      'Second item', 
      'Third item', 
    ), 
  ); 
}



Altering Content Inside a Render Array 

Altering the contents of a render array to change bits and pieces of the actual content is where you get into a very gray area. It could be argued that a change like this belongs inside a module. When making changes like this, it’s important to ask yourself whether or not the changes you are making should still apply when the theme you are developing is not active. Listing 16–20 changes the View and Edit tabs to read Profile and Edit profile on user profile pages.  ui


Listing 16–20. Implements hook_menu_local_tasks_alter() to Change Tab Names on User Profile Pages  
this

<?php 
/** 
* Implements hook_menu_local_tasks_alter(). 
*/ 
function dgd7_menu_local_tasks_alter(&$data, $router_item, $root_path) { 
  if ($root_path == 'user/%') { 
    // Change the first tab title from 'View' to 'Profile'. 
    if ($data['tabs'][0]['output'][0]['#link']['title'] == t('View')) { 
      $data['tabs'][0]['output'][0]['#link']['title'] = t('Profile'); 
    } 
    // Change the second tab title from 'Edit' to 'Edit profile'. 
    if ($data['tabs'][0]['output'][1]['#link']['title'] == t('Edit')) { 
      $data['tabs'][0]['output'][1]['#link']['title'] = t('Edit profile'); 
    } 
  } 
}



Notable Render Arrays in Core Templates 

There are quite a few render array variables scattered across core templates that are worth noting. hook_page_alter() contains the entire page so it can always be used to alter anything. However, finding that particular anything is not always trivial as other modules can move stuff around, so using more specific alters is advised. Table 16–2 is a quick reference of notable render arrays. This is by no means a full list, but it covers quite a bit and should give you an idea of how to begin figuring out where to look to edit these things. 
idea

Variable
Found in 
Alter Hook
Description 
$page
page.tpl.php 
hook_page_alter()
Contains the entire page from regions down to fields and comments. 
$content
node.tpl.php, 
comment.tpl.php, 
taxonomy-term.tpl.php
hook_node_view_alter(), 
hook_comment_view_alter(), 
hook_taxonomy_term_view_alter()
Contains the contents of each 
entity. For more details see 
http://api.drupal.org/hook_e
ntity_view_alter. 
$tabs
page.tpl.php 
hook_menu_local_tasks_alter() 
Contains primary and 
secondary tabs, themable via 
theme_menu_local_tasks() and
theme_menu_local_task(). 
$action_links
page.tpl.php
hook_menu_local_tasks_alter() 
Contains action links, 
themable via 
theme_menu_local_actions(). 
$item
field.tpl.php 
hook_field_display_alter() and 
hook_field_display_ENTITY_TYPE_
alter() 
Contains display settings for  fields, which can adjust label  settings or control the  formatter used to display the  contents of field.tpl.php.