Hi,

I tried to add a template file to my module which should be shown on a a page with the URL example.com/mymodule
But using the following code in the module's directory does not work for me:

function mymodule_theme() {
  return array(
    'mymodule' => array(
      'arguments' => array('node' => NULL, 'teaser' => FALSE, 'page' => FALSE),
      'template' => 'mymodule', // Template file without extension.
    ),
  );
}

or

function phptemplate_engine_preprocess_page(&$variables) { 
      $variables['template_files'][] ='mymodule'; 
}

The functions are not called automatically or they don't force drupal to show the template called mymodule.tpl.php in the mymodule directory, when calling example.com/mymodule, like when I implement mymodule_all() hook. What am I missing?

Thx, hama.

Comments

hamakabula’s picture

I found out, that using the preprocess function, I have to place my tpl.php file into the theme directory for it to work. How is it possible to just put it in the module's directory and still having the template displayed? Other modules like advanced_profile do this too, so it should be possible.
Btw, the functions above are just for testing purposes, I will add some conditions later not to have the module's template on every page ;)

Thx for any hint, hama.

hamakabula’s picture

*push*

jaypan’s picture

The theme function is correct. But I'm guessing you probably added this code after you had already installed the module. You need to clear the cache before your tpl.php file will be recognized.

Contact me to contract me for D7 -> D10/11 migrations.

hamakabula’s picture

Thanks for the answer, but I emptied the chache with the devel block, before. If I just use the mymodule_theme() function, there is an 404 error on the /mymodule page. If I use

function phptemplate_engine_preprocess_node(&$variables) {  
  $alias = drupal_get_path_alias($_GET['q']);
  if($alias == 'mymodule'){ 
    $variables['template_file'] = "mymodule"; 
  } 

instead, at least the template is used, when I put it in the theme's directory. But this is no good solution. I figured out, that it could be a problem reladet to Drupal being in a subdirectory like www.example.com/subdir/mymodule, now could it?

jaypan’s picture

Where are you placing the template file? It has to be in the module folder that you are defining hook_theme() in.

Contact me to contract me for D7 -> D10/11 migrations.

hamakabula’s picture

I'm sorry to bother you again, but for me it looks fine, even though it is probably some stupid mistake I cannot figure out myself.

# ls modules/contactpersons/ | grep tpl.php
cnt.tpl.php
contactpersons.tpl.php
# cat modules/contactpersons/contactpersons.module | grep -A 8 _theme
function contactpersons_theme() {
  return array(
    'contactpersons' => array(
      'arguments' => array('node' => NULL, 'teaser' => FALSE, 'page' => FALSE),
      'template' => 'contactpersons', // Template file without extension.
    ),
  );
}

Thanks a lot for your help,
hama

jaypan’s picture

I'm not sure exactly what you are showing me here. Of course I understand the theme function, but what is all this:

# ls modules/contactpersons/ | grep tpl.php
cnt.tpl.php
contactpersons.tpl.php
# cat modules/contactpersons/contactpersons.module | grep -A 8 _theme

Contact me to contract me for D7 -> D10/11 migrations.

hamakabula’s picture

The lines with a preceeding # are commands. The first one lists all templates in the directory modules/contactpersons, and one of them is contactpersons.tpl.php. The second one shows the line with the word _theme and the following 8 lines inside contactpersons.module. So it proves that the theme function is in the contactpersons.module which itself is in the same directory as the corresponding template file. I thought it would be more convincing than just to claim that the template file is in the correct directory.

jaypan’s picture

Ok, I get that. Sorry, I'm not a 'nix (which I'm guessing/assuming that is) guy, so it was all gibberish to me! haha

Anyways, so far everything looks good there - it should be working. So where/how are you calling the theme function? Can you show the function that contains the call to the theme function?

And just to clarify, you are doing this in a module right?

Contact me to contract me for D7 -> D10/11 migrations.

hamakabula’s picture

Anyways, so far everything looks good there - it should be working. So where/how are you calling the theme function? Can you show the function that contains the call to the theme function?

Oh my, I thought it would be called automagically like the preprocess function. I really read the theming documentation where hook_theme is mentioned many times. But I still couldn't find a good clue about where I should call the function. Just found a link to hook_theme_registry_alter, which should also provide the ability to add template files, if I understood this correctly. I want the template to be rendered as the node's content. Please give me a hint on where to call the function.

And just to clarify, you are doing this in a module right?

Yes, that's right.

jaypan’s picture

Well, you generate the content somewhere in your module. I can't really tell you where, because it will depend on the module. Then you call your theme function using theme([theme_function_name], $variable1, $variable2 ...);

The variables are defined in hook_theme. You then use the function that hook_theme defines to do whatever it is you want with the content being themed.

Contact me to contract me for D7 -> D10/11 migrations.

hamakabula’s picture

I can't follow you completely, so I will try to make the scenario more simple and concrete.
I have mymodule.module, the corresponding .info file and the template file mymodule.tpl.php as the only files in my mymodule directory. Now I want mymodule.tpl.php to be rendered when I call www.example.com/mymodule as the node's content. Therefore I try to register the template by adding the mymodule_theme function to mymodule.module. But the template will be rendered only if I call theme('mymodule_theme', 'variable_visible_in_template'); somewhere in mymodule.module. The problem is that I don't know where to do so. Do I have to call it inside a certain hook? Some preprocess function?

jaypan’s picture

I'll give you a simple example, with all the chaff removed:

<?php

// implementation of hook_menu
function mymodule_menu()
{
  $menu['mypage'] = array
  (
    'page callback' => 'drupal_get_form', //this function is called when example.com/mypage is accessed
    'page arguments' => array('mymodule_mypage'), // this value is passed to drupal_get_form. This means that the function with this name will be executed when accessing example.com/mypage
  );
  return $menu;
}

// callback function for the url example.com/mypage
function mymodule_mypage()
{
  $title = 'title'; // note: text should be wrapped in the t() function. But I'm omitting it for this example
  $contents[] = 'contents 1';
  $contents[] = 'contents 2';
  $contents[] = 'contents 3';
  // we now have string variable containing the title, and an array containing the contents contents. We will now pass these off to the theming function.
  $output = theme('mypage_display', $title, $contents); // we are using the theme function called 'mypage_display', and passing the $title variable and $contents array to it.
  return $output; // this will returns the themed contents to Drupal, which will insert them in the page
}

function mymodule_theme()
{
  return array
  (
    'mypage_display' => array // note: mypage_display is the function we called in our theme() function in mymodule_mypage()
    (
      'arguments' => array('title' => NULL, 'contents' => NULL),
      'template' => 'mymodule_mypage', // Template file without extension. The actual filename will be mymodule_mypage.tpl.php
    ),
  );
}
?>

Now finally, we have mymodule_mypage.tpl.php:

<?php
// Two variables are available in this page:
// * $title, a string which contains the title
// * $contents, ana rray which contains the contents.
?>
<h1><?php print $title; ?></h1>
<?php foreach ($contents as $content): ?>
<p><?php print $content; ?></p>
<?php endforeach; ?>
?>

Hopefully this helps. I didn't test any of it, so there may be syntax bugs, but for the most part it should give you the idea of how it works.

Contact me to contract me for D7 -> D10/11 migrations.

hamakabula’s picture

Hi,

It took me a while, but thanks to your code I do now understand a whole lot more how the menu system works. I remodeled your example to solve my problem and thereafter I understood the hook_theme_registry_alter like in a domino effect. So I came up with the following solution, as well.
ありがとうございます

So long, hama.

function MYMODULE_theme_registry_alter(&$theme_registry) {
  $template = 'node';  
  // dsm ($theme_registry);
  $originalpath = array_shift($theme_registry[$template]['theme paths']);
  // Get the path to this module
  $modulepath = drupal_get_path('module', 'MYMODULE');
  // Stick the original path with the module path back on top
  array_unshift($theme_registry[$template]['theme paths'], $originalpath, $modulepath);
} 

function MYMODULE_preprocess_node(&$variables) { 
  $alias = drupal_get_path_alias($_GET['q']);
  if($alias == 'nodealias1'){
    $variables['VAR'] = "blah"; //available in template as $VAR
    $variables['template_file'] = "TEMPLATE_FILE1"; //if template is XXX.tpl.php in your module directory TEMPLATE_FILE should be XXX without extension
  } 
  if($alias == 'nodealias2'){
    $variables['VAR'] =  "blah blah";
    $variables['template_file'] = "TEMPLATE_FILE2"; 
  } 
}
jaypan’s picture

どういたしまして :D

Contact me to contract me for D7 -> D10/11 migrations.