Need some help with your project? Contact me

How to access the node object from a template file

In this short tutorial I am going to show you how to access the node object from any template file. Say you need to work with some node information in a theme .tpl.php file and you don’t have access to the node content. What do you do? You get it from the URL. Come, I’ll show you.

The problem

Let’s say that you need to work with some variables from the node object currently loaded on the page. When you code from a .module file, you can implement hook_node_view(). This gets called whenever a node is loaded and with it comes a nice set of variables including the $node object we have come to love so much.

In many themes, you can access the same node object in various template files because it is made available by the template_preprocess() functions.

However you also have template files where you do not. This means you need to declare your own template preprocess function in order to send the node object currently loaded on the page. All good and well so far, you created the preprocess function skeleton, but you don’t know how to get the actual node object.

function themename_preprocess_hook($vars) {
  // unknown php code
}

The solution

I assume that you already know how to use the preprocess function to declare variables used in the .tpl.php file so I will not go over that here.

The solution to our problem is not so complicated. What you need to do is access the node ID (nid) found in the URL. As you know, every node page comes with a distinct URL in the form node/123. This means that if the path is in this format, not only you know that the page loads a node, but also which node is being loaded.

So that’s where we need to look. Inside the above preprocess function example I will show you how to get the current path and load the node based on that. Explanation comes after:

function themename_preprocess_hook(&$vars) {
   $path = isset($_GET['q']) ? $_GET['q'] : '<front>';
   $path = explode('/', $path);

   if ($path[0] == 'node' && isset($path[1])) {
     // creating the node variable
     $vars['node'] = node_load($path[1], NULL, TRUE);
   }
}

OK, so first we check if the q query string is set in the URL and if it is, we store it in a variable. If not, we just store the page. Next, we ‘explode’ it into an array with the forward slash as the separator. This will allow us to then check if the first part of the path is actually ‘node’, followed by a node ID as a second argument. If it is, then we use the node_load() function to load the respective node object and store it in the $vars[‘node’] variable that will be made available for the template file.

Now this was the long way. There is also a quicker way, using a Drupal API function called menu_get_object(). This will automatically and by default retrieve the node object loaded by the current router item. Additionally, by passing parameters, you can load other objects as well as from other paths. So basically all you have to do is say: $node = menu_get_object();

I wanted to show you both ways to better understand the logic behind retrieving objects based on the URL. Feel free to see which one suits better for you. Using the Drupal API is usually indicated though.

And that’s it. Not difficult is it? If you run into problems or have any questions, feel free to drop a comment. If you feel like a little homework, try on your own to apply the same principle to access the user object.

Comments

The Drupal 7 arg() function will take some of the complexity out of this for you:

function themename_preprocess_hook(&$vars) {
   if (arg(0) == 'node' && is_numeric(arg(1))) {
     // creating the node variable
     $vars['node'] = node_load(arg(1), NULL, TRUE);
   }
}

Thanks for your comment. I know about the arg() function, but it is preferable to use the menu_get_object() function if you're gonna use the Drupal API :)

Be careful when you load and print properties directly from the node object. Should an untrusted user be able to create nodes that are directly printed in the theme they have the ability to carry out a Cross Site Scripting attack since node values are raw and have not been run through check_plain() or any of Drupal's other sanitization and filtering functions. Here's also a video and explanation of XSS http://drupalscout.com/knowledge-base/introduction-cross-site-scripting-...

Thanks for your valuable comment!

This is indeed a good addition to my post. Once you get access to the node object, you need to keep in mind that things like title get saved as the user inputs them so you need to check_plain() them.

Should be using menu_get_object() just like core does in many instances.

Add new comment

You must have Javascript enabled to use this form.