Drupal Theme from Scratch Drupal Theme from Scratch icon
Theming a Drupal 7 Website



The Drupal 7 template.php File

Before we can explore the template.php file, we should first make sure you understand a little bit about PHP. If you are already comfortable with PHP, then proceed to the template.php stuff.

Understanding PHP

What do those snippets of code mean? Those snippets of code are actually a mixture of PHP and Drupal code.

Programming can be a difficult process to understand, but reading the code isn't quite as tricky. This example is one of the easier ones:

<?php print render($content['field_main_image']); ?>

And here's how to decipher it:

  • PHP code always starts with this: <?php and it always ends with this: ?>. These just tell your website's web server that whatever is in between these things needs to processed as PHP.
  • Print is a PHP command to display something in the browser — usually HTML or some text.
  • Render is a Drupal function that tells Drupal to grab the specified content from the database and process it (by possibly adding HTML tags to it or translating it into another language based on a user's preference) before adding it to the page.
  • $content is the Drupal variable that refers to the content for a given node. It actually contains a lot more than just your content. It also contains stuff like who created the content, when it was created, etc.
  • A node is an instance of any content type. Every event you create using the Event content type is a node.
  • field_main_image, in the above example, refers to the field with the 'machine name' of field_main_image for this particular node.
  • Each PHP statement will end with this: ; to tell the server that this particular command is finished and it can move on to the next command.

The way PHP works is simple. As long as you save your file with a .php extension on a web server that has PHP running, the server will know to look for your PHP code and process it properly. The resulting HTML is what will be sent to the browser. This is why you will not see any PHP code when you right-click and 'view source' in your browser.


Drupal's Template.php File

Now that you have practically no PHP knowledge (at least none from me), let's get more technical.
:)

The template.tpl.php file will be used to store any Drupal override functions you need. Preprocess functions in Drupal allow you to alter core functions before a given web page is rendered. Basically, if you have the desire or need to alter any of Drupal's core programming, you do it in THIS file. Never edit any core files.

When using any of the following functions, be sure to precede them with the machine name of your theme. Even though the template.php file is in your myTheme folder, Drupal needs to be reminded that the function in question is meant to work with your theme and your theme only.


Change Drupal's Search Form Input Type

The following code will alter the search form's input field type from 'text' to the HTML5 'search' type. This works by 'hooking' into Drupal's preprocess_search_box_form function and using PHP's str_replace function...

<?php
function myTheme_preprocess_search_block_form(&$vars) {
  $vars['search_form'] = str_replace('type="text"', 'type="search"', $vars['search_form']);
}
?>

Change and Add Attributes to a Drupal Form

This piece of code is altering two forms by 'hooking' into Drupal's form_alter function. The first snippet looks for the search form, then alters its label text, sets the label to invisible, sets the size of the field, adds some Javascript, adds some placeholder text and adds some classes.

The second snippet looks for the login form, makes the labels invisible, adds some placeholders and some Javascript to both the name and password fields. Finally, some additional JavaScript and a class are added to the form.

<?php
function myTheme_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'search_block_form') {
    $form['search_block_form']['#title'] = t('Search'); // Change the text on the label element
    $form['search_block_form']['#title_display'] = 'invisible'; // Toggle label visibilty
    $form['search_block_form']['#size'] = 40;  // define size of the textfield
    // Prevent user from searching the default text
    $form['#attributes']['onsubmit'] = "if(this.search_block_form.value=='Search'){ alert('Please enter a search'); return false; }";
    // Alternative (HTML5) placeholder attribute instead of using the javascript
    $form['search_block_form']['#attributes']['placeholder'] = t('Search');
    $form['search_block_form']['#attributes']['class'][] = 'search';
    $form['actions']['#attributes']['class'][] = 'element-invisible';
  }

  if($form_id == 'user_login' ) {
    $form['name']['#title_display'] = 'invisible';
    $form['name']['#attributes']['placeholder'] = t('User Name');
    $form['name']['#attributes']['onblur'] = "if (this.value == '') {this.value = 'User Name';}";
    $form['name']['#attributes']['onfocus'] = "if (this.value == 'User Name') {this.value = '';}";
    $form['pass']['#title_display'] = 'invisible';
    $form['pass']['#attributes']['placeholder'] = t('Password');
    $form['pass']['#attributes']['onblur'] = "if (this.value == '') {this.value = 'Password';}";
    $form['pass']['#attributes']['onfocus'] = "if (this.value == 'Password') {this.value = '';}";
    $form['#attributes']['onsubmit'] = "if(this.user_login.name.value=='User Name'){ alert('Please enter your user name'); return false; }";
    $form['#attributes']['onsubmit'] = "if(this.user_login.pass.value=='Password'){ alert('Please enter your password'); return false; }";
    $form['actions']['submit']['#attributes']['class'][] = 'button';
  }
}
?>

Notice that these two forms are being altered by the same function. This is because we can only call each function once. We can't call the myTheme_form_alter once for the search form and then a second time for the login form otherwise an error will be produced.

"Do we have to alter forms this way?" If you use Drupal's Form API, yes. If you create PHP forms on your own some how, then probably not. However, if you wish to take advantage of Drupal's built-in form security measures, you'll want to learn the Form API.


Turn Off Unnecessary Drupal Stylesheets

For the sake of speeding up your load time, especially on mobile devices, your can use the css_alter function to prevent CSS files from loading if they are not needed by your theme. They will still load on the backend as long as the backend is controlled by a different theme.

<?php
function myTheme_css_alter(&$css) {
  $exclude = array(
    'modules/comment/comment.css' => FALSE,
    'modules/node/node.css' => FALSE,
    'modules/search/search.css' => FALSE,
    'modules/system/system.menus.css' => FALSE,
    'modules/system/system.messages.css' => FALSE,
    'modules/system/system.theme.css' => FALSE,
    'modules/taxonomy/taxonomy.css' => FALSE,
    'modules/user/user.css' => FALSE,
    'modules/shortcut/shortcut.css' => FALSE,
    'modules/field/theme/field.css' => FALSE,
    'sites/all/modules/calendar/css/calendar_multiday.css' => FALSE,
    'sites/all/modules/date/date_api/date.css' => FALSE,
    'sites/all/modules/date/date_popup/themes/datepicker.1.7.css' => FALSE,
    'sites/all/modules/picture/picture_wysiwyg.css' => FALSE,
    'sites/all/modules/views/css/views.css' => FALSE,
    'sites/all/modules/ckeditor/css/ckeditor.css' => FALSE,
    'sites/all/modules/ctools/css/ctools.css' => FALSE,
  );
  $css = array_diff_key($css, $exclude);
}
?>

Your list of CSS files will of course be different than this one. Make sure not to cancel any that are needed by your theme or frontend modules. There may be some testing needed on your part but the list above has worked for me, so far.


Remove Drupal's Search Form from the Search Results Page

If you place your search form in your page header, then chances are good that you might not need it to show up again in another location.

<?php
function myTheme_form_search_form_alter(&$form, &$form_state) {
  if ((arg(1) == 'node') && (arg(2) != NULL)) {
    $form['#access'] = FALSE;
  }
}
?>

Drupal 7 User Page Templates

As if we didn't have enough templates to deal with. Now I'm showing you how to make more...

<?php
function myTheme_theme() {
  $items = array();
  $items['user_login'] = array(
    'render element' => 'form',
    'path' => drupal_get_path('theme', 'myTheme') . '/templates',
    'template' => 'user-login',
  );
  $items['user_register_form'] = array(
    'render element' => 'form',
    'path' => drupal_get_path('theme', 'myTheme') . '/templates',
    'template' => 'user-register-form',
  );
  $items['user_pass'] = array(
    'render element' => 'form',
    'path' => drupal_get_path('theme', 'myTheme') . '/templates',
    'template' => 'user-pass',
  );
  return $items;
}
?>

This function will allow you to create the following templates:

  • user-login.tpl.php ... access your new "login page" here: www.example.com/user
  • user-register-form.tpl.php ... access your new "user registration page" here: www.example.com/user/register
  • user-pass.tpl.php ... access your new "password recovery page" here: www.example.com/user/password

The following existing templates can be copied out of the modules/user folder and pasted into your templates folder for additional customization options...

  • user-profile.tpl.php
  • user-picture.tpl.php

Remember to always flush Drupal's cache after adding or creating new templates.


Remove List 'Item' Classes from Drupal Menus

Another good reason to create your own 'main' menu is if you want to remove the 'leaf' class from Drupal's menus. I found the solution here and wound up with my version below. This is an example of Drupal's theme_menu_link function which you would add to your template.php file.

<php
// remove 'leaf' class from menu li...
function myTheme_menu_link(array $variables) {
  // This is the part that removes or changes the 'leaf' class.
  if (!empty($variables['element']['#attributes']['class'])) {
    foreach ($variables['element']['#attributes']['class'] as $key => $class) {
      if ($class == 'leaf') {
        // To remove the 'leaf' class.
        unset($variables['element']['#attributes']['class'][$key]);
      }
    }
  }
  return theme_menu_link($variables);
}
?>

If you read the article I link to above, you can get more details on how this relates to making your own menus.


*If you do not see the social network icons here, it is because you have an ad-blocker running. Deactivate it for this site if you want to share this link. It is safe. There are no ads on this site.

This documentation is a work-in-progress. As I continue to learn more about the software, I will try to keep this documentation updated. I'm no expert of anything, so if anyone feels they need to correct me about something I've written or wish to add some additional tips, feel free to mention it in the comments.

"Drupal 7 Theme from Scratch" was written by TenTen71 because no one else would.