7.x node.api.php hook_node_view($node, $view_mode, $langcode)

Act on a node that is being assembled before rendering.

The module may add elements to $node->content prior to rendering. This hook will be called after hook_view(). The structure of $node->content is a renderable array as expected by drupal_render().

When $view_mode is 'rss', modules can also add extra RSS elements and namespaces to $node->rss_elements and $node->rss_namespaces respectively for the RSS item generated for this node. For details on how this is used, see node_feed().

Parameters

$node: The node that is being assembled for rendering.

$view_mode: The $view_mode parameter from node_view().

$langcode: The language code used for rendering.

See also

blog_node_view()

forum_node_view()

comment_node_view()

hook_entity_view()

Related topics

8 functions implement hook_node_view()

Note: this list is generated by pattern matching, so it may include some functions that are not actually implementations of this hook.

blog_node_view in modules/blog/blog.module
Implements hook_node_view().
book_node_view in modules/book/book.module
Implements hook_node_view().
comment_node_view in modules/comment/comment.module
Implements hook_node_view().
forum_node_view in modules/forum/forum.module
Implements hook_node_view().
node_test_node_view in modules/node/tests/node_test.module
Implements hook_node_view().

... See full list

4 invocations of hook_node_view()
field_attach_view in modules/field/field.attach.inc
Returns a renderable array for the fields on an entity.
field_view_field in modules/field/field.module
Returns a renderable array for the value of a single field in an entity.
node_build_content in modules/node/node.module
Builds a structured array representing the node's content.
node_build_content in modules/node/node.module
Builds a structured array representing the node's content.

File

modules/node/node.api.php, line 834
Hooks provided by the Node module.

Code

function hook_node_view($node, $view_mode, $langcode) {
  $node->content['my_additional_field'] = array(
    '#markup' => $additional_field,
    '#weight' => 10,
    '#theme' => 'mymodule_my_additional_field',
  );
}

Comments

Shiny’s picture

possible $view_mode contents include 'full' and 'teaser' amongst others

mjharmon’s picture

I note that the node object is not passed as reference and in my own experience with this hook, it's impossible to have changes made to the node (via this call) actually stick. (The title member as an example.)

I know that objects are allegedly passed by reference in PHP but that does not seem to be the case whenever I've attempted to use this function. This page: http://php.net/manual/en/language.oop5.references.php seems to suggest that objects are, in fact, not always passed by reference in PHP.

What am I doing wrong?

(And yes, I know I can use hook_node_alter_view if I really want to change the fields, but it would be so so much nicer if I could just make a call upstream to change what needs changing.)

Thank you.

mducharme’s picture

Perhaps you're looking for hook_view which is called before this function and has a return value of the node.

zirafa’s picture

Hook_view can only be called by node modules, ones that define the content type via hook_node_info. Maybe you are looking for hook_node_load?

zirafa’s picture

After playing around with this, hook_node_load seems like the simplest way to modify the node object.

However the "proper" way to modify small things seems to be to go down to the field level. But it gets very confusing quickly because there are lots of little hooks (see below) that seem to act on the field & entity level. Furthermore, empty field values don't seem to fire off any of these hooks, i.e. if $node->field_something is null, you can't hook into it.

hook_field_attach_view_alter
hook_field_formatter_view
hook_field_formatter_prepare_view
hook_field_load
hook_field_prepare_view
hook_entity_view_alter
hook_entity_load

It would be helpful to have a visual diagram or flowchart (if it doesn't already exist) showing the sequence of these hooks, and pointing to what part of the data loaded in the hook is actually modifiable. A lot of these little hooks seem to load read-only contextual data (i.e. a node object) or render arrays but for a developer implementing a hook function they want to know how to hook and modify one little part.

Furthermore with so many hooks there are many more places where data is altered, making tracing back changes more difficult than in previous versions of Drupal. Would appreciate any pointers from those in the know.

girishmuraly’s picture

Returning $node in hook_node_view() worked for me.

EDIT: Not returning $node as well is ok. Make sure your PHP version is >=5.2.5

girishmuraly’s picture

Only $node->content can be affected by this hook. Changes to $node->title or other elements are futile.

selinav’s picture

Which hook used to alter $node->title ?

murrow’s picture

firecentaur’s picture

Hi there, this took me a bit of searching as well!

After reading comments from this thread and others, I figured it out - here is what I did:

1) In my custom module called "Assignment" I added this:

function assignment_node_view($node, $view_mode) {
    if ($node->type=="assignment"){
        if ($view_mode == 'full'){
            $node->content['my_extra_content'] = array(
                 "#markup"=> '<div>My extra content!</div>',
                 "#weight"=> 100
              );   
           }
         return $node;
    }    
}

2) then in node--assignment.tpl.php, I added this:

if (array_key_exists("my_extra_content",$content)){
        print drupal_render($content["my_extra_content"]);
}

And that worked!

PROMES’s picture

In PHP > 5.3 the 'return $node;' isn't neccesary.

kpv’s picture

Don't forget to clear the cache

daniel.nitsche’s picture

PHP 5.2.13
Works: function hook_node_view($node, $view_mode)
Works: function hook_node_view(&$node, $view_mode)

PHP 5.3.2
Works: function hook_node_view($node, $view_mode)
Doesn't work: function hook_node_view(&$node, $view_mode)

Here's a discussion on a similar issue with the Webform module:
http://drupal.org/node/765308

insparrow’s picture

I was struggling with this quite a bit, but I have just figured it out. I've posted my code below in case anyone else comes across this problem.

function yourmodule_node_view(&$node, $view_mode, $langcode) {
$strBody = $node->content['body'][0]['#markup'];
$node->content['body'][0]['#markup'] = 'my additional text' . $strBody;
}

Tested on PHP 5.2.10

Kind Regard
Emma

Exlord’s picture

tanks it worked for me ... was looking for this for hours ...

edu2004eu’s picture

You are a queen! No solution in this thread worked for me, except yours. Thank you!

sonictruth’s picture

If you neglect to add a condition to check the view mode then this hook will fire when running cron (not sure why but it does, trust me).

I had a drupal_goto() inside a hook_node_view() which was causing a whole bunch of 'Warning: Cannot modify header information' errors in the logs and cron failed to run because drupal_goto() ends up calling drupal_exit().

So when ever you use this hook always check the view mode like so:

function modulename_node_view($node, $view_mode, $langcode) {
  if ($node->type == 'node-type' && $view_mode == 'full') {
    // Code here.
}
manarth’s picture

this hook will fire when running cron

This is usually because search is trying to view the node, in order to build its search index. Generally I'd try to avoid using drupal_goto in hook_node_view at all.

mchitten’s picture

Just because this isn't very clearly identified, I think it's worth pointing what the possible parameters for the array are:

function hook_node_view($node, $view_mode, $langcode) {
  $node->content['my_additional_field'] = array(
    '#markup' => $additional_field, 
    '#weight' => 10, 
    '#theme' => 'mymodule_my_additional_field',
  );
}

#markup is the output. You can use a function callback if you want, or just slap a string in there. Whichever is more convenient for you.
#weight defines where the item lays on the page (assume that the base content has a weight of 0).
#theme denotes a theme function that will define how the information is displayed. You'll often find #theme looking something like this...

'#theme' => 'links__node__blog'

...This calls the theme() function. Check out that page to see how the theme() function parses data.

---
Here's some more that aren't in this documentation:

#links is associated with the 'links_node_blog' '#theme' above. It is an associative array of links (including href, title and attributes) that will be displayed. Check out the Blog module for a good look at this one.

#attributes are your standard attributes, as seen in other functions. You can define class, ID...pretty much anything with arrays. For example:

'#attributes' => array('class' => array('links', 'inline'))

There's probably more. I'm still finding them myself.

gollyg’s picture

The array being returned here is an example of a render array. It is not documented in this function (it would be beyond the scope of this documentation), but you can read more about them at http://drupal.org/node/930760.

Indexes like '#links' are node-specific properties, so they won't be documented in the information about render arrays, but they will follow the same logic.

rooby’s picture

gopiraj_m’s picture

One I've come accross is item_list. Could you list out the others deafults too? Been searching, couldn't get.

W.M.’s picture

I tried the following but it did not work:

'#attributes' => array('class' => array('links', 'inline'))

redsd’s picture

The example looks a bit incomplete, it didn't work for me, however this did:

function hook_node_view($node, $view_mode, $langcode) {
  $additional_field = 'My extra text here';
  $node->content['my_additional_field'] ['my_additional_field'] = array(
    '#markup' => $additional_field, 
    '#weight' => 10, 
    '#theme' => 'mymodule_my_additional_field',
  );
}
tamerzg’s picture

If you need to render image link you would do it as followed:

$node->content['links']['fb'] = array(
      '#links' => array(
        array(
          'title' => '',
          'html' => TRUE, 
          'href' => 'http://www.facebook.com/dialog/feed',
        ),
      ),
    );

Important is to add html = TRUE otherwise title would render as plain text.

Ambidex’s picture

This might be worth noting that this hook will not be called before for example page.tpl.php, I tried adjusting the $node->title, but this did not adjust the page title. But after inspecting the node object in the node.tpl.php it actually was adjusted.

joachim’s picture

The $page parameter that D6 has isn't available, but you can check whether the given node is being shown as a full node page with:

if ($node = menu_get_object()) {
$nid = $node->nid;
}
dieuwe’s picture

I had much trouble with most of the examples given, but at the end this is what I did to get it working in its simplest form:

function hook_node_view($node, $view_mode, $langcode) {
  $node->content['my_additional_field'][0] = array(
    '#markup' => 'Hello World', 
  );
}
er.pushpinderrana’s picture

I have tried all above solution but at the end, this simple example worked for me.

Hello World !!!!! :-)

kalidasan’s picture

Use above code with proper condition as per your requirements.

function hook_node_view($node, $view_mode, $langcode) {
  global $user;
  if($node->type == 'content-type' && $view_mode == 'full' && isset($user->roles[15]))
 {
    $node->content['custom_field'] = array(
      '#markup' => 'Hello World',
      '#weight' => 3, // Weight to re-arrange your display.
    );
  }
}
roynilanjan’s picture

Can we use the below snippet w.r.t #theme

function hook_node_view($node, $view_mode, $langcode) {
  global $user;
  if($node->type == 'content-type' && $view_mode == 'full' && isset($user->roles[15]))
 {
    $node->content['custom_field'] = array(
      '#theme' => 'test',
      '#var1' => 'some-val',
    );
  }
}

using the above snippet we can call a theme-key name test which is already registered by hook_theme() then we need not use render() function in theme layer as
$content['custom_field']; will produce it self a rendered data

sanduhrs’s picture

doar1004’s picture

Please help me to convert this function below to drupal 7, I have tried using hook_node_view but no luck.

 function publication_nodeapi(&$node, $op = 'view', $teaser = FALSE, $page = FALSE)
    {
        if($op == 'view')
        {
            $publication_menu = get_publication_content_ids();
            $extraContent = '';
            $extraContent .= '<link href="'.base_path().drupal_get_path('module', 'publication').'/css/style.css?t" rel="stylesheet" type="text/css" />';
            switch($node->nid)
            {
                case $publication_menu[0]:
                    $extraContent .= publication_index();
                break;

                case $publication_menu[1]:
                    $extraContent .= search_publication();
                break;

                case $publication_menu[2]:
                    $extraContent .= howtoorder_index();
                break;

                case $publication_menu[3]:
                    $extraContent .= kiprahagroforestry_index();
                break;
            }
            $node->content['body']["#value"] .= $extraContent;
        }
    }

Your advice really appreciate it.

Thanks

ali butt’s picture

i am confused that $node is neither being passed as reference (&$node) nor the hook returns $node, even then how is it possible that local $node is making changes in actual node content...
Some one please explain me

skein’s picture

$node is an object and objects are passed by reference every time.

benjifisher’s picture