1

here is a good one that has always stumped me.

I would love to see a solution in both D6 and D7.

I create custom modules and usually work with the menu api to create menu type -> MENU_CALLBACK.

Here is an example:

function example_menu() {
  $items['example/page1'] = array(
    'page callback'     => 'example_page1_callback',
    'access callback'   => TRUE,
    'type'              => MENU_CALLBACK,
  );
  return $items;
}

I would like to see the exact code solution to provide three different variables to be printed in a custom theme template based on the following code. To add to that challenge, I would like the code to be written in the menu callback function only. I know there are many possible ways to do it but could never figure out how to do it in a menu callback function which would be the most useful way.

//****************************************
// This code block goes in a custom module called example_menu_variables.module

// hook_menu example
function example_menu() {
  $items['example/page1'] = array(
    'page callback'     => 'example_page1_callback',
    'access callback'   => TRUE,
    'type'              => MENU_CALLBACK,
  );
  return $items;
}

// hook_meny callback function
function example_page1_callback() {
  // please provide code within this function to turn these next three
  // variables into separate output variables for the template.
  $variable_to_print1 = 'Foo';
  $variable_to_print2 = 'Bar';
  $variable_to_print3 = array('bing', 'bang', 'bong');
  return;
}
//****************************************



//****************************************
// This block of code represents the part of the custom theme template related to the menu location from the hook_menu call
// D6 template name would be page-example-page1.tpl.php
// D7 template name would be page--example--page1.tpl.php

<div><?php print  $variable_to_print1?></div>
<div><?php print  $variable_to_print2?></div>
<div><?php print  $variable_to_print3[0] . ' ' . $variable_to_print3[1] . ' ' . $variable_to_print3[2]?></div>

/*
output should look like:
Foo
Bar
bing bang bong
*/

//****************************************

Hope this is the kind of problem that someone wouldn't mind solving. Thanks for your time. :)

Ray James

2
  • If I understand you correctly, that is the purpose of hook_theme(). Why does the code need to be contained within the menu callback function? Commented May 3, 2013 at 17:07
  • Hi Adam and thanks for the response. I guess it would be great to see what the code would look like both ways. Using hook_theme() requires a ton of setup just to get one custom variable into the theme layer. I would like a simple solution that can be done in the same place that you would be gathering your data from the database to display as output. It would be really great to have a function that just sends that variable like this -> drupal_add_template_variable($var, $varname); or something like that. I am not sure if such a thing exists in Drupal. Thanks. Commented May 3, 2013 at 19:04

5 Answers 5

1

I got this working in Drupal 7, simply by setting the variable in the render array returned from the page callback.

In .module file

function example_page1_callback() {
$render_array['variable_to_print1'] = 'Foo';
$render_array['variable_to_print2'] = 'Bar';

// set other render array items for the page

return $render_array;
}

In page.tpl.php file

<div class="someDiv">
  1st variable = <?php print render($page['content']['system_main']['variable_to_print1']); ?><br />
  2nd variable = <?php print render($page['content']['system_main']['variable_to_print2']); ?><br />
</div>
1
  • My god man you did it! You figured it out! You totally rock. I have one edit though. It's system_main not system-main for Drupal 7 at least. Thank you so much. Commented Jan 23, 2014 at 20:29
6

I don't believe you can do this without using hook_theme, but this is exactly what it's for and it's quite simple. (This code is for Drupal 6.)

/**
 * Implements hook_menu().
 */
function example_menu() {
  $items['example/page1'] = array(
    'page callback'     => 'example_page1_callback',
    'access callback'   => TRUE,
    'type'              => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Page callback function
 */
function example_page1_callback() {
  $variable_to_print1 = 'Foo';
  $variable_to_print2 = 'Bar';
  return theme('example_contents', $variable_to_print1, $variable_to_print2);
}

/**
 * Implements hook_theme().
 */
function example_theme() {
  return array(
    'example_contents' => array(
      'arguments' => array('variable_to_print1' => null, 'variable_to_print2' => null),
      'template' => 'example-contents',
    ),
  );
}

$variable_to_print1 and $variable_to_print2 are now available in example-contents.tpl.php.

7
  • Hi Adam, thanks for the code. I put it together and ran it but got a ton of errors stating that all the other standard variables are undeclared -> Notice: Undefined variable: logo in include() (line 92 of C:\xampp\htdocs\d7themeaddvar\site\themes\bartik\templates\example-contents.tpl.php) I put the files in a git repository for easy download -> github.com/rayjames/d7themeaddvar Commented May 3, 2013 at 20:39
  • content-example.tpl.php does not replace page.tpl.php. Only the defined variables will be available in it (in this case $variable_to_print1 and $variable_to_print1). If you want to make a new variable available to page.tpl you should look into hook_preprocess(). Commented May 3, 2013 at 20:47
  • Hmm, we seem to be going in a different direction here. I'm not sure what your code does anymore. As per the initial problem, I asked for code to make variables for print in a custom template, but I guess I need to be more specific because I assumed everyone would understand that the hook_menu item would point to a "page" on the site and that there would be a custom template for said "page" that the variables would be available for. I can't figure out how to get your code to print the variables. Thanks. Commented May 3, 2013 at 21:03
  • 1
    @rayjamesfun With the best will in the world, you're heading in entirely the wrong direction at the moment. Drupal has a templating system, if you want to take advantage of that you need to follow its rules, which Adam has outlined perfectly. If you don't, then you'll need to resort to plain ol' PHP which we can't get into here; we offer Drupal solutions here, not solutions to get around Drupal :)
    – Clive
    Commented May 3, 2013 at 21:53
  • Hi Clive. I hear ya, and I totally agree. I'm in now way trying to go around Drupal, just looking for an easier solution that I already thought was there. I can't get Adam's code to work. I am no newb to Drupal. I have built some extremely complex sites but still can't seem to figure out how to wield the theme system like a ninja. Just looking for a complete example solution at this point in the way of the Drupal. Thanks. Commented May 3, 2013 at 22:02
2

The code written by Adam is correct (my +1) Your variables are available in example-contents.tpl.php file - it is a template file of your module output.

However, if you need these variables in page.tpl file, then you can just create them:

in your module file:

/**
 * Page variables
 *
 * @return
 *  custom page variables
 */ 
function custom_variables(){

  $variable_to_print1 = 'Foo';
  $variable_to_print2 = 'Bar';
  $variable_to_print3 = array('bing', 'bang', 'bong');

  return array( 'variable_to_print1'    => $variable_to_print1,
                'variable_to_print2'    => $variable_to_print2,
                'variable_to_print3'    => $variable_to_print3
  );
}

in your template.php file:

/**
 * Override or insert variables into the page templates.
 *
 * @param $variables
 *   An array of variables to pass to the theme template.
 * @param $hook
 *   The name of the template being rendered ("page" in this case.)
 */
function YOURTHEME_preprocess_page(&$variables, $hook) {

  // pass your module variables to page--example1.tpl.php file
  if (in_array('page__example1', $variables['theme_hook_suggestions'])){
    if (module_exists('your_module')){
        $your_module_variables = custom_variables();
        $variables['variable_to_print1'] = $your_module_variables['variable_to_print1'];
        $variables['variable_to_print2'] = $your_module_variables['variable_to_print2'];
        $variables['variable_to_print3'] = $your_module_variables['variable_to_print3'];
    }
  }
}
2
  • Hi Jack, is this a D6 or D7 solution? I was wondering if you could link to the tutorial or Drupal page that might explain what is going on in your code better too. I am assuming that you do not know of a solution that can be implemented within the menu callback, correct? I am also assuming that you would/could write a different function for each "page" so as to keep the variables organized. This doesn't look like it would work with a page that has dynamic page arguments either. Thanks. Commented May 4, 2013 at 2:08
  • 1
    All above mentioned examples works perfect. My answer concerning a D7 solution. It doesn't matter if your page has dynamic arguments or not. Your variables will be available on every "example1" page ("example1" it's a content type) If you need them on every content type page, then just remove the first IF statement in preprocess_page from my example. You can create your variables anywhere (in your module for example) but then, they have to pass through YOURTHEME_preprocess_page function, because it's the place where your variables are defined as a page variables.
    – Jack-PL
    Commented May 4, 2013 at 12:59
1

Had same problem, this is what worked for me on Drupal 7.x

function example_menu() {
  $items['example/page1'] = array(
  'page callback'     => 'example_page1_callback',
  'access callback'   => TRUE,
  'type'              => MENU_CALLBACK,
  );
return $items;
}


function example_page1_callback() {
  $variable_to_print1 = 'Foo';
  $variable_to_print2 = 'Bar';
  $variable_to_print3 = array('bing', 'bang', 'bong');

  //use below given statement when you only want to pass one variable
  // to your template
  //return theme('example',array('output'=>$variable_to_print1));

  //use this statement when you want to pass array
  return theme('example',array('output' => $variable_to_print3)); 
}

In addition to all this you need a example_theme() hook

function example_theme(){
    //lets say your template file is called example.tpl.php and it resides
    //within your module directory.
    $custom_example_template = array();

    $custom_example_template['example'] = array(
        'template' => 'example',
        'variables' => array('output' => NULL)
    );
}

Now what about your example.tpl.php

<div id='someotherid'>
    <?php
             //use this code when you have passed only one variable
             print $variables['output'];
    ?>
</div>

You can name your variables whatever you want, you don't need to stick with 'output' as I did. For some reason you can't see my foreach loop to loop through the array we have passed.

1
  • I don't believe this will pass the variables to page.tpl.php, i.e. header, footer; only to the content. Commented Mar 10, 2015 at 21:41
0

I got Jack's method to work, although I must say the render_array idea is simpler. Here's what worked for me:

In Module:

//page callback to create the page and include some CSS & Javascript
function my_callback() {
   drupal_add_css(...); 
   drupal_add_js(...); 
   return '';   
}

function _my_module_vars(){
   $var1 = 'foo'
   $var2 = 'bar'
}

In theme's Template.php

function MYTHEME_preprocess_page(&$vars) {
   //add some custom variables to the module page
    if(in_array('page__my_content_type', $vars['theme_hook_suggestions'])) { 
       if(module_exists('my_module')) { 
          $my_vars = _my_module_vars();  
          $vars['var1'] = $my_vars['var1'];
          $vars['var2'] = $my_vars['var2'];
    }
  }
}

In page.tpl.php (or you could use page--my_content_type.tpl.php):

print $var1; 
print $var2; 
1
  • Just to clarify, the reason I also wanted to do this way (as opposed to hook_theme in the module method) is that here, the variables are available in the page.tpl.php file. In the hook_theme way, the module template file is rendered into the page's content variable (if I remember correct), which makes it tough to do much with it. Commented Nov 14, 2013 at 17:43

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.