Using theme hooks to display a tpl.php on a menu path

The Node, Views and Panels modules can (and should!) handle most pages you need on a site, but sometimes you need complete control of a "hard coded" content area. You could create a new Page node with a Full HTML text format. Instead, how about putting the whole thing in code? Your work will be in version control and much more straightforward to maintain. Imagine editing HTML in a text editor rather than in the Drupal admin! So much better. Additionally, this method allows you to work more easily in a git-based workflow, such as those used by Pantheon or Acquia, without worrying about database changes.

Warnings for the less experienced Drupal site builder: This is specifically written to enforce the theme and logic separation functionality Drupal provides; no logic in the tpl files! If you can make a page in Views, it should be in Views. If you can make it in Panels, it should be in Panels. Do not use this method to recreate the wheel. If you find yourself writing large amounts of SQL queries in the page callback, then you are probably doing something wrong. Do it the "Drupal Way." Your life will be less stressful in the long run. /rant

Ok! Let's get to the code. First thing, make an info file for new module. Be sure to change the "variables" below to match your site and the page/app name.
sitename_pagename.info:

name = Site Name - Page Name
description = Creates the Page Name for the Site Name
core = 7.x
package = Site Name
version = 7.x-1.0

Then make the module with hook_menu(), a page callback, hook_theme(), and a preprocess function.
sitename_pagename.module:

<?php
/**
 * Implements hook_menu()
 */
function sitename_pagename_menu() {
  $items['page-path'] = array(
    'title' => 'Page Name',
    'type' => MENU_NORMAL_ITEM,
    'page callback' => 'sitename_pagename_page_main',
    'access arguments' => array('access content'),
  );
  return $items;
}
 
/**
 * Page callback sets up and returns the content for the Page Name page
 */
function sitename_pagename_page_main() {
  $module_path = drupal_get_path('module', 'sitename_pagename');
  // Add any required jQuery libraries JavaScript. DELETE IF UNNECESSARY!
  drupal_add_js($module_path . '/library.min.js');
  // Add the module path to Drupal.extend. DELETE IF UNNECESSARY!
  $data = array(
    'sitename_pagename' => array(
      'path' => $module_path,
    ),
  );
  drupal_add_js($data, 'setting');
  // Add the custom JavaScript. DELETE IF UNNECESSARY!
  drupal_add_js($module_path. '/sitename_pagename.js');
  // Add the page CSS. DELETE IF UNNECESSARY!
  drupal_add_css($module_path . '/sitename_pagename.css');
 
  // Render the theme function for this page
  // NOTE: Pass any required variables to theme function using array, see Drupal API.
  return theme('sitename_pagename_main', array('hello' => t('Hello')));
}
 
/**
 * Implements hook_theme.
 */
function sitename_pagename_theme() {
  return array(
    'sitename_pagename_main' => array(
      'variables' => array(
        // Specifies both available variables.
        'hello' => NULL,
        'world' => NULL,
      ),
      // This allows you to create a tpl file named sitename_pagename_main.tpl.php.
      // It will be automatically loaded by Drupal.
      'template' => 'sitename_pagename_main',
    ),
  );
}
 
/**
 * Implements hook_preprocess_THEME().
 *
 * This Example preprocesses some variables to pass to the theme function/file.
 * DELETE IF UNNECESSARY! You probably won't need it, but it is here as an example
 */
function sitename_pagename_preprocess_sitename_pagename_main(&$variables) {
  // Use view_embed_view or related here.
 
  // As an example, this fills in the world variable sitename_pagename_page_main() didn't.
  $variables['world'] = t("World!");
}

Finally, make the template file.
sitename_pagename_main.tpl.php:
<strong><?php print $hello;?> <?php print $world;?></strong>

Put the module and code in $DRUPAL_ROOT/sites/all/module/custom/sitename_pagename/. Enable your new module and check the new page at: sitename.com/page-path/

Update 7/5/13: New article using this method to implement a template file for a custom block with an admin page to manage it: Instead, how about a Drupal block with a custom settings form?

Comments

Thanks man !!

Thanks a lot! Really helped out!

Gracias, información muy buena.
Thanks, information very good.

Thanks.

Add new comment