Can I overwrite the url function of a specific content type of node entity ? So to have a different pattern when i use: $node->url();


Entity URI callback

You can implement an URI callback. Example in comment.module:

 * Entity URI callback.
function comment_uri(CommentInterface $comment) {
  return new Url(
      'comment' => $comment->id(),
    ['fragment' => 'comment-' . $comment->id()]

and add the callback to the annotations of the entity type:

*   uri_callback = "comment_uri",

For an existing entity use a hook_entity_type_alter().

Bundle specific URI callback

A URI callback for a specific content type can be defined in the bundle definitions:

 * Implements hook_entity_bundle_info_alter().
function mymodule_entity_bundle_info_alter(&$bundles) {
  if (isset($bundles['node']['my_content_type'])) {
    $bundles['node']['my_content_type']['uri_callback'] = 'my_content_type_uri';

The callback:

 * Bundle URI callback.
function my_content_type_uri(NodeInterface $node) {
  // build a url object $url
  return $url;

A bundle-specific callback takes precedence over the generic one for the entity type and a link template (defined in the links array of the entity type) takes precedence over both, so you need to remove the link template if you want to override an existing one, e.g. canonical, which makes you responsible to provide the route needed for the custom url, if it was built before by a route provider and is not defined in a *.routing.yml file.


To modify the url in links to a specific content type you can use a hook_link_alter():

function mymodule_link_alter(&$variables) {
  $url = $variables['url'];
  if ($url->isRouted() && $url->getRouteName() == 'entity.node.canonical') {
    if (isset($variables['options']['entity'])) {
      $node = $variables['options']['entity'];
      if ($node->bundle() == 'article') {
        // modify the links to articles
  • This is what I understand how the code works, but how does the mentioned uri callback of the comment module gets called for canonical urls, when the comment entity has a link template defined? – 4k4 Jul 24 '17 at 16:56
  • Indeed the uri callback in the comment module does not run during normal operation of the site. comment::permalink() adds the fragment instead. – 4k4 Jul 24 '17 at 19:03
  • ! Don't work: function commerce_entity_bundle_info_alter(&$bundles) { if (isset($bundles['node']['product_display'])) { $bundles['node']['product_display']['uri_callback'] = 'product_display_uri'; } } function product_display_uri(NodeInterface $node) { return Url::fromRoute('my.route'); } $node->url(); get canonical url @4k4 – BOES Jul 28 '17 at 11:00
  • This is the problem I've described. If you use url() without parameter you get the canonical link and this will be returned according to the link template in the entity definition. – 4k4 Jul 28 '17 at 11:34
  • I would like to overwrite the method, so that the views (for example, content) automatically have the new url. What do you advise ? – BOES Jul 28 '17 at 13:49

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.