Drupal - Preprocess function per content type

The zen subtheme accomplishes this by adding this to its theme_preprocess_node function:

function foo_preprocess_node(&$variables, $hook) {
  ...
    // Optionally, run node-type-specific preprocess functions, like
  // foo_preprocess_node_page() or foo_preprocess_node_story().
  $function = __FUNCTION__ . '_' . $variables['node']->type;
  if (function_exists($function)) {
    $function($variables, $hook);
  } 
  ...
}

If you have a content type called 'news', then you would be able to create a function called foo_preprocess_node_news in your template.php file.


The name of the preprocess function is based on the theme name, so for theme_table() your preprocess function is MYTHEME_preprocess_table().

Since there is no theme_node_node_type function a preprocess hook such as foo_preprocess_news or foo_preprocess_node_news won't work out of the box.

You could go about overriding the theme registry so that it behaves differently for nodes, but I really wouldn't recommend it; it could get very messy.

I'm a huge fan of refactoring code but in your case I don't think it's necessary; if you have complex logic that needs to run in your preprocess hook dependent on node type then farming it out to different functions in the way you currently doing seems like good practice to me.

The other method, of course, would be to implement a custom module for each of the different content types and implement hook_preprocess_node() in each. That way, each module's preprocess function can be responsible for a different content type.

However this may be overkill for your situation; if you don't have extra logic (i.e. non theme preprocess logic) to perform on each content type, then this method probably doesn't add any extra value.


I only just had a similar issue which is why google brought me to this page: my node preprocess function was growing so enormously big, that i would rather split the function into multiple files.

I've already done a similar approach in my template.php file which contains all the alter functions, and since the same method works perfectly well here, I thought I'd share my approach:

file setup inside the folder MYTHEME/preprocess:

- node.preprocess.inc
- node--blog-post.preprocess.inc
- node--device-variation.preprocess.inc
- (...)

you should already have node.preprocess.inc, the others you can create yourself. how you call them really is rather arbitrary, but better give them names that nicely identify them and fit the whole drupal naming system.
onwards to the content of these files!

node.preprocess.inc, here I'm doing doing something like this:

<?php

function MYTHEME_preprocess_node(&$variables) {

    switch($variables['type']) {

      case 'blog_post':
        // if the type of the node is a Blog Post, include this:
        include 'node--blog-post.preprocess.inc';
        break;

      case 'device_variation':
        // if Device Variation, include this:
        include 'node--device-variation.preprocess.inc';
        break;

      case 'foo':
        // ...
        break;
    }

    // additional stuff for all nodes

}

we basically switch through the type of the current node. what you switch through is up to you; #id, #view_mode, all depending on your exact needs.
once there is a match, it will load the specified file and act upon its content just as if it was written right inside this function.

the content of these included files looks exactly like you'd put it in the node.preprocess.inc file, except we don't call the preprocess function again:

node--device-variation.preprocess.inc

<?php

    // Device Name
    $device = drupal_clean_css_identifier(strtolower($variables['title']));

    // Determine whether only Device Version is of type 'N/A' and set ppvHasVariations accordingly
    $deviceHasVariations = true;
    if( $variables['content']['product:field_model_variation'][0]['#options']['entity']->weight == 0 ) {
        $deviceHasVariations = false;
    }
    //...

you can basically do this with as many files as you want and even cascade multiple switches, for example further splitting up specific node preprocess files depending on the #view_mode, having one file for the full view mode and another for the teaser

hope this helps, should someone ever stumble upon this question again (:

Tags:

Theming

7