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']); ?>
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. |
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
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 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'); } } }
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. |