64

In Drupal 7, if I wanted to get the node id of the currently displayed node (e.g. node/145) I could get it with the arg() function. In this case, arg(1) would return 145.

How can I achieve the same in Drupal 8?

128

The parameter will have been upcasted from nid to full node object by the time you get access to it, so:

$node = \Drupal::routeMatch()->getParameter('node');
if ($node instanceof \Drupal\node\NodeInterface) {
  // You can get nid and anything else you need from the node object.
  $nid = $node->id();
}

See the change record for more information.

8
  • 8
    I just want to add you have to careful with this - I just got stung where \Drupal::routeMatch()->getParameter('node'); will return an array of 1 item (the node id) on node revision delete pages, so if you calling a method on what you assume to be an object you will get a fatal error like "Fatal error: Call to a member function getType() on string".
    – Jeff Burnz
    Aug 10 '16 at 1:13
  • How can I get parameter, if I visited /taxonomy/term/{tid}?
    – AshwinP
    Mar 27 '17 at 12:40
  • 1
    Is this a functional replacement for menu_get_object? May 2 '18 at 17:09
  • Pretty much yes @Frank. It’s a bit different of course, but if you’re dropped in a context that doesn’t know what entity page (if any) it’s on, this is the recommended way to find out
    – Clive
    May 2 '18 at 18:03
  • 1
    @AshwinP The parameter is whatever you write inside {} in your route. For taxonomy terms the route paramater is called taxonomy_term, route definition /taxonomy/term/{taxonomy_term}. Here you can get it like this, \Drupal::routeMatch()->getParameter('taxonomy_term').
    – user72672
    Aug 22 '19 at 8:40
21

It is correct to use \Drupal::routeMatch()->getParameter('node'). If you just need the node ID, you can use \Drupal::routeMatch()->getRawParameter('node').

6

if you are using or creating custom block then you have to follow this code to get current url node id.

// add libraries
use Drupal\Core\Cache\Cache;  

// code to get nid

$node = \Drupal::routeMatch()->getParameter('node');
  $node->id()  // get current node id (current url node id)


// for cache

public function getCacheTags() {
  //With this when your node change your block will rebuild
  if ($node = \Drupal::routeMatch()->getParameter('node')) {
  //if there is node add its cachetag
    return Cache::mergeTags(parent::getCacheTags(), array('node:' . $node->id()));
  } else {
    //Return default tags instead.
    return parent::getCacheTags();
  }
}

public function getCacheContexts() {
  //if you depends on \Drupal::routeMatch()
  //you must set context of this block with 'route' context tag.
  //Every new route this block will rebuild
  return Cache::mergeContexts(parent::getCacheContexts(), array('route'));
}
0
5

Note on the node preview page, the following doesn't work:

$node = \Drupal::routeMatch()->getParameter('node');
$nid = $node->id();

For the node preview page, you have to load the node this way:

$node = \Drupal::routeMatch()->getParameter('node_preview');
$nid = $node->id();

How to load node object in node preview page?

-1

By using Service,

    use Drupal\Core\Routing\RouteMatchInterface;

/**
 * Provides a 'UtilitiesDataService' service.
 */
class MyClass {
 

  /**
   * The route match.
   *
   * @var \Drupal\Core\Routing\RouteMatchInterface
   */
  protected $routeMatch;

  /**
   * Constructs a new service.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The route match.
   */
  public function __construct(RouteMatchInterface $route_match) {

    $this->routeMatch = $route_match;
  }

  public function getNodeId(){
    $nid = $this->routeMatch->getParameter('node')->id();
  }
}

In services.yml file,

services:
   my_module.get_data_service:
    class: Drupal\my_module\MyClass
    arguments: ['@current_route_match']
1
  • This is not "by dependency injection" - this is the creation of a new service. You're going to write a new service just to wrap one method of the existing current_route_match service? This is just wrong. Use @Clive's answer, which accesses the current_route_match service directly.
    – anonymous
    Oct 1 at 20:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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