function hook_node_view

You are here

7 node.api.php hook_node_view($node, $view_mode, $langcode)
8 node.api.php hook_node_view(\Drupal\node\NodeInterface $node, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $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 831
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

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

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.

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

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?

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.

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

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

Which hook used to alter $node->title ?

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!

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

Don't forget to clear the cache

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

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

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

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

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.
}

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.

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.

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.

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

<?php
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',
  );
}
?>

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

<?php

$node

->content['links']['fb'] = array(
     
'#links' => array(
        array(
         
'title' => '<img src="/images/icfbk.jpg"/>',
         
'html' => TRUE,
         
'href' => 'http://www.facebook.com/dialog/feed',
        ),
      ),
    );
?>

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

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.

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:

<?php
if ($node = menu_get_object()) {
$nid = $node->nid;
}
?>

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:

<?php
function hook_node_view($node, $view_mode, $langcode) {
 
$node->content['my_additional_field'][0] = array(
   
'#markup' => 'Hello World',
  );
}
?>

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

Hello World !!!!! :-)

Use above code with proper condition as per your requirements.

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

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

<?php
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

<?php
hook_theme
()
?>

then we need not use render() function in theme layer as

<?php
$content
['custom_field'];
?>

will produce it self a rendered data