0

So I posted this question about how to get NID of current node and I'm assured that arg() should work to return the router item for the current page, regardless of aliasing. However, it doesn't work.

The relevant snippet is

if(arg(0)=='node' && is_numeric(arg(1))){ 
   $nid = arg(1); 
   dsm($nid);
}

I've also tried

$load = node_load();
$dsm($load);

and

$item = menu_get_item();
dsm ($item);

and

$node = menu_get_object();
dsm($node);

For all of these methods, they work when I edit the page (and thus make the URL displayed become /node/%/edit) and when I just navigate to /node/% (where % is the NID) but they display either nothing or (in the case of arg()) only the alias (e.g. "about-our-company for the path alias /about-our-company).

How can I reliably get the NID of the current node?

6
  • Where did you place your php code? In a module (which hook?), in a node, in a block, somewhere else? May 29, 2012 at 13:22
  • Where are you calling your code from? If it's in a template file then the results of the dsm() call will likely be delayed by one page, which might give the impression it's not working.
    – Clive
    May 29, 2012 at 13:23
  • It's in a module.
    – beth
    May 29, 2012 at 13:46
  • @beth Help us help you :) where in your module file? What hook is it in? And what are you actually trying to accomplish here? There might be an easier way
    – Clive
    May 29, 2012 at 13:51
  • It's not in anything. I haven't written anything else in the module yet. Is it really so complicated to find out the NID of the current node?
    – beth
    May 29, 2012 at 15:01

2 Answers 2

3

Your code is failing because you're putting it directly in the module file, and not using the hook system. I won't go into exactly why this won't work, if you read the Module Developer's Guide it'll make sense.

It's a bit tricky to advise what hook your code should be going in as you don't mention what you want to do with it. As an example, though, lets say you want to extract the nid from the current page and pass it to an external service somewhere outside of Drupal.

There are several different ways to do it; at the most basic level, you could use hook_init(), which is called on every page load. Using this method your calls to menu_get_object() and arg() will yield the result you're expecting:

function MODULENAME_init() {
  $node = menu_get_object();

  if (isset($node->nid)) {
    send_data_to_external_service($node->nid);
  }
}

That's all fine, but let's say you want to change the content of a node based on it's nid. hook_init() will be no good for this, as it has no node available to manipulate in the current context.

Instead, Drupal actually provides a hook that is called when any node in the system is prepared for view, allowing you to manipulate the content. This hook is called hook_node_view(), and can be used like this:

function MODULENAME_node_view($node, $view_mode, $langcode) {
  if ($view_mode == 'full') { // Node is being viewed on it's full node page
    $node->content['my_additional_field'] = array(
      '#markup' => $additional_field, 
      '#weight' => 10, 
      '#theme' => 'mymodule_my_additional_field',
    );
  }
}

Notice that one of the arguments that's passed to the function is the $node object, which contains the nid as a property. As you have this object in the current context, there's no need to query menu_get_object() or arg() to get the nid.

There are dozens of different hooks in Drupal that respond to different system events, and allow your custom modules to have a say in how a page is displayed/how data is saved/etc. It might be a good exercise to read through that list and see which hooks would help with the development of your own module.

2
  • Wonderful, thanks for pointing out my mistake. This actually clarified my understanding of Drupal rather than just providing a workaround.
    – beth
    May 29, 2012 at 18:06
  • No worries, have a look at this question too, the answers do a great job of explaining what the hook system is and how it's used
    – Clive
    May 29, 2012 at 19:08
3

arg() is intended to work with system paths. if you are viewing you node page with system path (node/#) or by alias then arg(1) must return nid of the node.

How are you defining your alias? Are you using path module interface?
Perhaps the alias is a result of a custom menu hook by some module, rendering a node by some arbitrary logic.

I would also like to share a hack to overcome this issue if you get alias in arg() and this alias is truly defined by path module directly on node then drupal_lookup_path('source', 'your/node/alias') will return the system path of your node e.g. node/#

3
  • 1
    I agree with the first two paragraphs, but drupal_lookup_path() will only return node/% if the provided alias is actually an alias of the node. If that were true, arg() and menu_get_object() would already work
    – Clive
    May 29, 2012 at 13:34
  • Aliases are being generated by Pathauto.
    – beth
    May 29, 2012 at 13:47
  • 1
    @Clive, Yes I intended as you said. I have updated the statement. May 29, 2012 at 13:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.