2

I'm attempting to make my first custom node template that is supposed to be used for a certain content type with the machine name of "content_block." I copied the "/modules/node/node.tpl.php" file to my theme's directory at "/sites/all/themes/mytheme." Then I renamed the file to "node--content_block.tpl.php."

Then I cleared the site's cache via "Administration » Configuration » Development » Performance."

It seems to only be partially working. Some of my content type's field variables render, but not with the values I expect. Others don't render anything but the word "Array".

My template code looks like this:

<div id="node-<?php print $node->nid; ?>" class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>>
  <?php if ($field_headline == TRUE && $field_headline != " "): ?>
    <?php print render($title_prefix); ?>
    <?php print $field_headline_level; ?><?php print $title_attributes; ?>><?php print $field_headline; ?></<?php print $field_headline_level; ?>>
    <?php print render($title_suffix); ?>
  <?php endif; ?>  
  <div class="content"<?php print $content_attributes; ?>>
    <?php print $field_content; ?>
  </div>
</div>

One thing I definetly don't understand is when to use print render($variable) and when to use print $variable.

  • I discovered that some of my fields are now rendering correctly after I moved my template files into a template directory in my theme. But for my longtext field called field_content I'm getting this output Array property="dc:title" datatype="">Array Configure Array – Ben Dec 5 '11 at 15:20
2

render() renders the argument it gets using drupal_render(), and the documentation for this function reports the following text:

Renders HTML given a structured array tree.

Recursively iterates over each of the array elements, generating HTML code.

Renderable arrays have two kinds of key/value pairs: properties and children. Properties have keys starting with '#' and their values influence how the array will be rendered. Children are all elements whose keys do not start with a '#'. Their values should be renderable arrays themselves, which will be rendered during the rendering of the parent array. The markup provided by the children is typically inserted into the markup generated by the parent array.

HTML generation for a renderable array, and the treatment of any children, is controlled by two properties containing theme functions, #theme and #theme_wrappers.

#theme is the theme function called first. If it is set and the element has any children, it is the responsibility of the theme function to render these children. For elements that are not allowed to have any children, e.g. buttons or textfields, the theme function can be used to render the element itself. If #theme is not present and the element has children, they are rendered and concatenated into a string by drupal_render_children().

The #theme_wrappers property contains an array of theme functions which will be called, in order, after #theme has run. These can be used to add further markup around the rendered children; e.g., fieldsets add the required markup for a fieldset around their rendered child elements. All wrapper theme functions have to include the element's #children property in their output, as it contains the output of the previous theme functions and the rendered children.

The other elements that influence how the element passed to drupal_render() (or render()) is rendered are:

  • #type, which causes the array to be merged with the array returned by element_info()
  • '#pre_render, which causes the element to be passed to a function that alters the element before is rendered
  • #post_render, which causes the element to be passed to a function that alter the rendering result

The following are all examples of rendering arrays that you can pass to render() (and drupal_render()):

$markup = array(
  '#type' => 'markup',
  '#markup' => '<div class="messages">' . t('This is the message') . '</div>',
);
$form['nodes'] = array(
  '#theme' => 'table', 
  '#header' => $header, 
  '#rows' => $options, 
  '#empty' => t('No content available.'),
);
  $node->content['links']['node'] = array(
    '#theme' => 'links__node__node', 
    '#links' => $links, 
    '#attributes' => array('class' => array('links', 'inline')),
  );

In the first example, the array is extended by element_info() (as the array contains the #type property) and what is really used from render() is the following array:

$markup = array(
  '#type' => 'markup',
  '#markup' => '<div class="messages">' . t('This is the message') . '</div>',
  '#pre_render' => array('drupal_pre_render_markup'),
);

You can also pass a string to render(), as the code that the function executes is the following one:

if (is_array($element)) {
    // …
}
else {
  // Safe-guard for inappropriate use of render() on flat variables: return
  // the variable as-is.
  return $element;
}

This means that it is safe to call the function with a string.

 

As in the comment for your question you are referring to a node field, fields are always passed to render(); if "field_name" is the ID of the field found in the node, then you render it using the following code:

render($content["field_name"]);
| improve this answer | |
4
  • Use print render when the variable is a build array and use
  • Use print when the variable is a PHP string containing HTML.

For more details, render arrays on d.o. (render and build arrays are the same thing).

| improve this answer | |
  • Would a field that I create in a content type ever be a build array? And how do I know the difference. (I don't really understand what a build array is, other than it's an array created when building the page). – Ben Dec 5 '11 at 15:21
0

This is how I ultimately solved my problem (though the render() explanations were good too). Custom Content types nodes with Nodeblocks module

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.