In mymodule_node_view(), I set the theme function to be used with the following code.

$node->content['#theme'] = "my_custom_theme_function";

Now the node preprocess function (mymodule_preprocess_node()) is not called anymore.

How do I let Drupal run my node preprocess function, even if I set my theme function to be used?

1 Answer 1


With that line, you set the theme function for all the content shown for the node. Your code should be similar to the following one, taken from the documentation for hook_node_view().

function mymodule_node_view($node, $view_mode, $langcode) {
  $node->content['mymodule_field'] = array(
    '#markup' => $additional_field,
    '#weight' => 10,
    '#theme' => 'mymodule_custom',

As to why your code is setting the theme function for all the node content, see the code executed by node_view(). (The comments are mine.)

  // This is the function that invokes hook_node_view().
  node_build_content($node, $view_mode, $langcode);

  $build = $node->content;

  // $node->content['#theme'], the value you set, becomes $build['#theme'].


  // The following lines don't set anymore $build['#theme'], since you have already set it.
  // It is similar to executing the following code:
  //   $a = array('first' => "I am the first");
  //   $a += array('first' => "The array will never get this value");
  // If you print the value of $a, you will see it is as it was first set.

  $build += array(
    '#theme' => 'node',
    '#node' => $node,
    '#view_mode' => $view_mode,
    '#language' => $langcode,

  // Now the code is going to use your theme function, which means that not even
  // the node preprocess function is executed.

Normally, what you want to do is adding a new content to the render array for the node. That is what the code I show in the first snippet does.

If you really wanted to change the theme function used for the node, then you should simply implement hook_theme_registry_alter(), and redefine the function associated with the node theme function.

Keep in mind that once you change the used theme function, also the preprocess function changes; in your case, if theme_my_custom_theme_function() is your theme function, then the preprocess function is mymodule_preprocess_my_custom_theme_function().

  • This complicates it a bit. I only want to change the theme for one node type, which means to output this node type with a completely custom html (I didn't write it originally, but the change of #theme was inside an if($node->type=='myspecial')). And still have a preprocess function called, to load javascript etc. This would normally be done in a theme (like adaptive theme) using a custom tpl.php for a node type, but I need this html defined by a module, independent of the theme. If I change the theme registry, it will change the node theme for all node types.
    – camcam
    Commented Sep 1, 2013 at 11:05
  • The theme function receives three arguments: the node, the view mode, and the language. If the theme should be applied to specific content types, $node->type is available.
    – apaderno
    Commented Sep 1, 2013 at 21:29
  • So, when I use the theme function (as originally) then the preprocess function is not called. On the other hand, when I use theme_registry_alter, then it applies to all node types (because it's called when clearing cache, not when node is displayed). I need something that applies only for one node type and allows preprocess functions being called (and allows to rewrite the node HTML completely).
    – camcam
    Commented Sep 1, 2013 at 22:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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