10

In my custom theme's hook_preprocess_page() and hook_preprocess_html() functions, I often need to identify the same information. Rather than essentially running the same if statement checks in both the identify the same info, it would make much more sense to just do it once in both of them and then pass that info to the other preprocess function. How can I do this? I tried the following but it didn't work:

function myTheme_preprocess_page(&$vars){
    $vars['myValue'] = 7;
}

function myTheme_preprocess_html(&$vars){
    //$vars['myValue'] should equal 7...
}

I also tried it the other way around (setting the value in the preprocess html function and then retrieving it in the page preprocess function) but that didn't work either. Which brings up a related question: in what order are these preprocess functions, er, processed? It seems to me that the page preprocess function comes before the html one, is that correct?

14

You're going to need either a global or static variable to accomplish this...personally I'd recommend going with static and implementing a generic helper function using Drupal's static pattern like so:

function _myTheme_var($var_name, $new_val = NULL) {
  $vars = &drupal_static(__FUNCTION__, array());

  // If a new value has been passed
  if ($new_val) {
    $vars[$var_name] = $new_val;
  }

  return isset($vars[$var_name]) ? $vars[$var_name] : NULL;
}

function myTheme_preprocess_page(&$vars){
  $vars['some_var'] = _myTheme_var('my_var', 7); // Set the value and retrieve it
}

function myTheme_preprocess_html(&$vars){
  $vars['some_var'] = _myTheme_var('my_var'); // Get the value
}

The $vars arrays for each preprocess function are completely different objects in memory so you won't be able to use that array to pass things around. I've seen this sort of pattern used a lot in Drupal core so I think it would be the best way to go.

EDIT

Oh and yes, hook_preprocess_page() is called before hook_preprocess_html()...as far as I'm aware Drupal works in a sort of "inside-out" manner so hook_preprocess_html() would probably be the last one that's run in a page build.

3

I accomplished this with a similar case of 'node' and 'page' by doing:

function mymodule_preprocess_node(&$vars) {
  _mymodule_preprocess_vars($vars,'node');
}

function mymodule_preprocess_page(&$vars) {
  _mymodule_preprocess_vars($vars,'page');
}

function _mymodule_preprocess_vars(&$vars, $where) {

  // all vars common to both node and page set here

  switch($where) {

    case 'node':

      // node only vars set here;

      break;

    case 'page':

      // page only vars set here;

      break;
  }
}

so I'd imagine it would work similarly with 'page' and 'html' instead.

  • Yes, that would work. But it's not very efficient because those $vars that need some kind of processing would have that processing done multiple times. – maxedison Mar 5 '12 at 14:37
  • true, if it's something heavyweight in common between preprocess functions, like setting a variable to some complex sql result, yes, you probably don't want to be doing it multiple times, but that's easily solved with some static processing like the first answer. and light weight settings might actually be faster since you don't have the function call overhead for each and every variable set, just the first time in calling from main function. And obviously the major portions (node & page) only get set once. – Jimajamma Mar 5 '12 at 16:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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