1

I have a path /application, which is rendered by a custom module (through a combination of theme hook/controller/routing/twig). It's basically a mini-application.

I also have a Drupal node /data, which is a Drupal node with content loaded by Drupal.

However, I need to load the contents of /application at /data. I tried setting the routing of my custom module to use /data instead of /application, but Drupal still loads the Drupal node content at /data rather than the custom module content. The catch is, this particular application uses fields from that node, so I don't want to delete the node. I just want to change what gets rendered when you view the node, but leave it active and editable.

What's the best way to accomplish this?

6
  • In order to load variables before the node is rendered, you need to use HOOK_preprocess_node, did you try that? Commented Apr 30, 2022 at 6:05
  • Change the node’s path to something that isn’t /data. Problem solved.
    – Clive
    Commented Apr 30, 2022 at 9:46
  • 1
    @Clive Ideally I'm not changing the node path because I want to retain where the node is used in menus. Is there no way to override the view of a node with a custom module?
    – Anton
    Commented Apr 30, 2022 at 11:35
  • 1
    @HodbaKhalaf I tried that but can't see a way to load everything from a custom module into the node viewer. Any idea how this could be done?
    – Anton
    Commented Apr 30, 2022 at 11:36
  • 1
    Drupal first uses the path aliases, then the routes defined from modules. If you were to add a node with /admin/config/people/accounts as path alias, you won't see anymore the settings page for the accounts.
    – avpaderno
    Commented Apr 30, 2022 at 11:38

1 Answer 1

2

Since /data is a path alias for a node, Drupal shows that node instead of showing what a controller associated to that path returns. If you were to set a node path alias to /admin/config/people/accounts, Drupal would show that node instead of the accounts setting page.

If you want to change the render array used for a node, you need to implement hook_ENTITY_TYPE_view(). You can compare $entity->id() with the node ID to which you want add data in its render array.

use \Drupal\Core\Entity\EntityInterface;
use \Drupal\Core\Entity\Display\EntityViewDisplayInterface;

/**
 * Implements hook_ENTITY_TYPE_view().
 */
function mymodule_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  if ($entity->id() == 3) {
    // Change $build.
  }
}

You can also find the node ID given its path alias, for example with code similar to the following one.

use \Drupal\Core\Entity\EntityInterface;
use \Drupal\Core\Entity\Display\EntityViewDisplayInterface;

/**
 * Implements hook_ENTITY_TYPE_view().
 */
function mymodule_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  $path = \Drupal::service('path_alias.manager')->getPathByAlias('/data');

  if (preg_match('/node\/(\d+)/', $path, $matches)) {
    if ($entity->id() == $matches[1]) {
      // Change $build.
    }
  }
}

See How can I get the node ID from a path alias? which also explains when to use the path_alias.manager or the path.alias_manager service.

(As a side note, if I were to use this code in sites where the content is exported from a site and imported in those sites, I would compare the node UUID with the value I expect for the node I need to handle. This works only when the node UUIDs are kept when importing content.)

2
  • 1
    Great idea! I was able to load my custom module content instead here by adding to $build. One question I have for this is: inside hook_ENTITY_TYPE_view(), instead of using the $entity->id(), is there any elegant way to use the custom module's routing.yml to get and call the appropriate controller method dynamically? Otherwise I'm hard-coding ids which feels the same as just creating a 'node--3.html.twig' type of override, and also hard-coding what controller and method to load content from.
    – Anton
    Commented Apr 30, 2022 at 14:39
  • You can get the node ID given the path alias, as I show in the updated answer. The code is still hard-coding a value (the path alias), but it's easier to set the same path alias on different sites than getting the same node ID for nodes on different sites.
    – avpaderno
    Commented Apr 30, 2022 at 17:46

Your Answer

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

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