Theming Drupal can be like working with layers of an onion. There are layers and layers and sometimes cutting through makes you cry. Besides not knowing what theme function or template file one must use (Drupal 8 helps with the knowing part with html comments) there is the big problem of global state and context, and the theme layer you're trying to use might be missing some context. The major example is that you want some block to be aware of the node on the page. (This is a problem which React.js helps deal with by passing state from parent to child component via props.)
But outside of the node template there's no natural awareness of a "current node" and the node ID isn't passed down or around even when it's known. Most of those pieces are supposed to not care. But there are many times we want to display content one way based on some aspect of the "current" node on the page. How do we get access to this node?
The answer depends on the version of Drupal.
How to get nid from the url Before Drupal 6: arg()
In the olden days, there was
arg($n), a function which returned the $n-th parameter of the URL before any aliasing. So a normal Drupal node page would have a url like
http://example.com/node/1234 even if there was a URL alias of
http://example.com/an-example pointing to it. So what
arg(0) would return is
arg(1) would return
arg(1) gives us our
nid with which we can
node_load(1234) to get our full node. This could be done anywhere to get access to "this node" including in block code.
Drupal 6 / Drupal 7: menu_get_object()
This method still worked in Drupal 6 & 7 but then a new and more explicit method was added: menu_get_object defined as "on the page node/%node, the router loads the %node object, and calling menu_get_object() will return that."
$node = menu_get_object(); $node->nid == arg(1);
This only works if the core menu entry for nodes hasn't been overridden.
Drupal 8: It's Complicated
As of Drupal 8,
arg() is deprecated so the hack doesn't work anymore. Also,
menu_get_object was removed. And with Drupal 8's new object-oriented everything approach, you'll now need a much longer expression to get at the node.
<?php namespace Drupal; $node_v1 = \Drupal::request()->attributes->get('node'); $node_v2 = \Drupal::routeMatch()->getParameter('node') ?>