Author image
Senior Developer

Get the entity for a route

In Drupal 7, we had menu_get_object() to get the object in code for whichever node, term, or whatever entity makes up the current page. But in Drupal 8, that has been replaced, and entities can usually be operated on in a generic way. If you know the type of entity you want, it's pretty simple. But I keep running into different suggestions of how to get the entity object when you don't know its type. Given that D8 allows us to deal with entities in a unified way, I thought there must be a good way! The code of core itself is usually the best place to look for examples of how to do common things. I found that the content translation module has a smart way of doing it, which I've adapted here for more general use:

/**
  * Helper function to extract the entity for the supplied route.
  *
  * @return null|ContentEntityInterface
  */
function MYMODULE_get_route_entity() {
  $route_match = \Drupal::routeMatch();
  // Entity will be found in the route parameters.
  if (($route = $route_match->getRouteObject()) && ($parameters = $route->getOption('parameters'))) {
    // Determine if the current route represents an entity.
    foreach ($parameters as $name => $options) {
      if (isset($options['type']) && strpos($options['type'], 'entity:') === 0) {
        $entity = $route_match->getParameter($name);
        if ($entity instanceof ContentEntityInterface && $entity->hasLinkTemplate('canonical')) {
          return $entity;
        }

        // Since entity was found, no need to iterate further.
        return NULL;
      }
    }
  }
}

// Example usage:
$entity = MYMODULE_get_route_entity();
$entity_type = $entity ? $entity->getEntityTypeId() : NULL;

Routes for entities keep the entity under a parameter on the route, with the key of the parameter being the entity type ID. Looping through the parameters to check for the common 'entity:...' option finds identifies the parameters that you need. The above code will only work for the current path. But if you can get hold of the route object for a given path/URL, then you could do something similar.

It seems a shame to me that this isn't any simpler! But hopefully this at least helps you understand a bit more about routes for entities.