Need some help with your project? Contact me

I’m Hooked! 6: Altering node content before it’s rendered on the page in Drupal 7

This week’s post will look at how to use hook_node_view() to add or change node content before being rendered on the page. This is a powerful API tool used by many contrib modules to intervene at this final stage when the renderable array is already created.

To illustrate the power of this hook, I will first show you how to add new content to the node being displayed on the page. Additionally, I will show you how to programatically change the display style of an image field using this hook.

Like I said, hook_node_view() gets called in the final stage of content delivery, after it is assembled and before is being rendered onto page. Moreover, it takes three parameters: $node (the node being assembled), $view_mode (the view mode it is currently on), and $langcode (the language code).

Adding or modifying node content

In the first example, let’s say we have Article nodes which have a body and an image field. Below these fields, we want to add a list of items that our module generates dynamically depending on the node being loaded. In this example, I’m going to hardcode this list because it is not the focus of the article, but you’ll get the point.

A simple function to return an array that will constitute the list items:

function demo_get_list_items() {
  $array = array("car", "cat", "dog");
  return $array;
}

Now we can look at the hook. I will write the code and then explain:

function demo_node_view($node, $view_mode, $langcode) {  
  $array = demo_get_list_items();
  $list_vars = array(
    'items' => $array,
    'type' => 'ul',
  );
  if($view_mode == 'full') {
    $node->content['list'] = array (
      '#markup' => theme('item_list', $list_vars),
      '#weight' => 3,
    );
  }
}

First of all, I advise you to use the Devel module to look inside the $node object for orientation. The $node->content array is what in Drupal talk you call a renderable array, ready to be displayed on the page. This is where we include our list, right below the body field.

So the function above does the following. First, it retrieves the list items and prepares another array to be passed to the theme() function later on. Then, it checks to see that the view mode of the node is 'full' (to avoid this injection to be done in teasers or other view modes).

Inside this conditional, a new array is set within the $node->content array, with the key list. We pass the markup to be used for our list and the weight (in this example 3 is fine since we want it to come at the end of the Article node fields).

The theme() function will use the Drupal item_list theme to render our array into an unordered html list. We pass it also the array of parameters we declared a bit earlier.

And this is pretty much it. If you clear the cache and go see any node, you’ll see your list appear below the body field. But I’ll let you go ahead and figure out how you can limit the list to appear only on Article nodes. Hint: krumo the $node object and use what is in there in the php if conditional.

Note: Using this hook does not add any new information to the database nor it creates new fields attached to the node. If the module gets disabled, the content you add using this hook will no longer appear. Additionally, if you use something like the Display Suite module to create custom layouts for your nodes, content you add outside of already existing fields will not show.

Changing the image style

This second example comes from what I promised you last week and is quite simple in fact. All you need to do is replace the image style used for rendering the image in the node. This is the code:

function demo_node_view($node, $view_mode, $langcode) {  
  if($view_mode == 'teaser') {
    $node->content['field_image'][0]['#image_style'] = 'demo_image';
  }
}

Here, we make sure that our demo_image image style gets applied only to nodes being viewed in teaser mode. Within the php conditional, we simply replace the #image_style property of the image field. And that’s it. Clear the cache and you’ll see the changes.

So these are very simple ways you can use hook_node_view(). If you look what the $node object gives you to work with, I'm sure you can find many uses for this hook. Incidentally I used it in my contrib module Block Inject to make changes to the body field. Check it out if you want to see how I used it there.

Hope this helps. Any trouble, drop a comment.

Comments

Note that you can also use #theme (+ the theme function parameters) without need to call the function yourself. Like this:


function demo_site_node_view($node, $view_mode, $langcode) {
if ($view_mode == 'full') {
$node->content['list2'] = array (
'#theme' => 'item_list',
'#items' => demo_get_list_items(),
'#type' => 'ol',
'#weight' => 0,
);
}
}

Hey there, thanks for your comment.
Indeed you are right, but I wanted with this occasion to also show the use of the theme function -> if you can squeeze more API tools in there, why not? :)

Cheers!

Hi,
Thanks for the information. I am by following your tutorial i used devel module and there i find $node->title which is the title of the node currently being viewed. How ever in the mentioned hook i tried to overwrite the title but nothing is changed.

Can you please clear this confusion.

Thanks

Hello!

I have been banging my head with Drupal theming all evening now and wondering why you use hook_node_view
and not hook_node_view_alter
or hook_entity_view_alter?

Hi there,
A lot more to grasp from your content but a little help will be appreciated,
what if:
I create a blog listing view in which it show several blogs in teasers form which displays(presently) blog title, blog content, than its image but i want to display blog image, title than blog teaser can i achieve that in Views thanks in advance

Hello!

Probably you have to write on second line
$array = demo_get_list_items();
instead of
$array = get_list_items();

Hey there,

Thanks! Corrected.

How to add CSS class to the inserted field or HTML markup? Thanks.

I am trying to add custom div before the node title please guide me.

Add new comment

You must have Javascript enabled to use this form.