I've been working on custom modules that alter RequestEvent
s based on the entity type provided by the route.
The functionality from one entity to another doesn't change, but the data does, hence I split the module. The working example extends a class provided by a base module that holds the core functionality.
I'm not sure if it matters, be it run order precedence or what have you, but the names are akin to my_module_nodes
and my_module_taxonomy_terms
.
When I have just my_module_nodes
installed, it works perfectly. When I install my_module_taxonomy_terms
alongside it, my_module_taxonomy_terms
appears to override the functionality of my_module_nodes
.
I've debugged by logging to Watchdog the routes I'm checking against with both modules enabled, and it checks for the route defined in my_module_taxonomy_terms
twice, rather than checking for the routes defined in each individual module. E.g. I would expect to see entity.node.canonical
logged as well as entity.taxonomy_term.canonical
, but I see entity.taxonomy_term.canonical
logged twice per page load.
Note that I have attempted this with static strings in the __construct
method as opposed to using arguments from the services file, but nothing changing. Also note that installation order does not change the result - my_module_taxonomy_terms
always overrides my_module_nodes
.
One of the two submodule event subscribers in question - identical to the other besides the data
method.
/custom/my_module_base/src/MyModuleBaseSubscriberBase.php
namespace Drupal\my_module_base;
use Drupal\Core\Cache\CacheableJsonResponse;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Routing\CurrentRouteMatch;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* @package Drupal\my_module_base\JsonEntitySubscriberBase
*/
class MyModuleBaseSubscriberBase implements EventSubscriberInterface {
/** @var \Drupal\Core\Cache\CacheBackendInterface */
protected $cacheBackend;
/** @var \Drupal\Core\Routing\CurrentRouteMatch */
protected $routeMatch;
/** @var string */
protected $routeName;
/** @var string */
protected $routeParameter;
/**
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* The "cache.render" cache backend service.
* @param \Drupal\Core\Routing\CurrentRouteMatch $route_match
* The "current_route_match" route match interface service.
* @param string $route_name
* The Name of the route to check against.
* @param string $route_parameter
* The Name of the route parameter to get.
*/
public function __construct(CacheBackendInterface $cache_backend, CurrentRouteMatch $route_match, string $route_name, string $route_parameter) {
$this->cacheBackend = $cache_backend;
$this->routeMatch = $route_match;
$this->routeName = $route_name;
$this->routeParameter = $route_parameter;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('cache.render'),
$container->get('current_route_match'),
$container->get('route.name'),
$container->get('route.parameter'),
);
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = ['onRequest', 29];
return $events;
}
/**
* @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
* The current RequestEvent object.
*/
public function onRequest(RequestEvent $event) {
$request = $event->getRequest();
$route_match = $this->routeMatch->getRouteMatchFromRequest($request);
if ($route_match->getRouteName() !== $this->routeName) {
return;
}
$event->setResponse($this->getResponse(
$route_match->getParameter($this->routeParameter)
));
}
// Other functionality...
/**
* @param mixed $entity
* @return array
*/
protected function getData(mixed $entity): array {
return [
'type' => $entity->getEntityTypeId(),
'id' => $entity->id(),
];
}
}
One of the two submodule event subscribers in question - identical to the other besides the data
method.
/custom/my_module_base/modules/my_module_nodes/src/EventSubscriber/MyModuleNodesSubscriber.php
namespace Drupal\my_module_nodes\EventSubscriber;
use Drupal\my_module_base\MyModuleBaseSubscriberBase;
/**
* @package Drupal\my_module_nodes\EventSubscriber
*/
class MyModuleNodesSubscriber extends MyModuleBaseSubscriberBase {
/**
* {@inheritdoc}
*/
protected function getData(mixed $entity): array {
return [
'type' => $entity->getEntityTypeId(),
'id' => $entity->id(),
// Other values...
];
}
}
One of the two submodule service files in question - identical to the other besides the parameters
values.
/custom/my_module_base/modules/my_module_nodes/my_module_nodes.services.yml
parameters:
route.name: entity.node.canonical
route.parameter: node
services:
my_module_nodes.subscriber:
class: \Drupal\my_module_nodes\EventSubscriber\MyModuleNodesSubscriber
arguments: ['@cache.render', '@current_route_match', '%route.name%', '%route.parameter%']
tags:
- { name: event_subscriber }
I've been tinkering on this project over the past week after work and I'm at a bit of a loss. Is there any other relevant information I should include? Thanks!