Comme suggéré par Berdir, vous pouvez regarder le module Devel et comment il l'implémente. Le code suivant a été "extrait" de Devel
1) Créez les itinéraires
Créez le fichier mymodule.routing.yml dans et à l'intérieur définissez un rappel de route (qui est utilisé pour créer les routes dynamiques)
route_callbacks:
- '\Drupal\mymodule\Routing\MyModuleRoutes::routes'
Créez la classe MyModuleRoutes pour générer vos routes dynamiques dans src / Routing
<?php
namespace Drupal\mymodule\Routing;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
class MyModuleRoutes implements ContainerInjectionInterface {
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->entityTypeManager = $entity_type_manager;
}
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity_type.manager')
);
}
public function routes() {
$collection = new RouteCollection();
foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
if ($entity_type->hasLinkTemplate('canonical')) {
$route = new Route("/mymodule/$entity_type_id/{{$entity_type_id}}");
$route
->addDefaults([
'_controller' => '\Drupal\mymodule\Controller\MyModuleController::doStuff',
'_title' => 'My module route title',
])
->addRequirements([
'_permission' => 'access mymodule permission',
])
->setOption('_mymodule_entity_type_id', $entity_type_id)
->setOption('parameters', [
$entity_type_id => ['type' => 'entity:' . $entity_type_id],
]);
$collection->add("entity.$entity_type_id.mymodule", $route);
}
}
return $collection;
}
}
2) Créez les tâches locales dynamiques
Créez le fichier mymodule.links.task.yml et définissez à l'intérieur un dérivé
mymodule.tasks:
class: \Drupal\Core\Menu\LocalTaskDefault
deriver: \Drupal\mymodule\Plugin\Derivative\MyModuleLocalTasks
Créez la classe MyModuleLocalTasks pour générer vos routes dynamiques dans src / Plugin / Derivative
<?php
namespace Drupal\mymodule\Plugin\Derivative;
use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class MyModuleLocalTasks extends DeriverBase implements ContainerDeriverInterface {
protected $entityTypeManager;
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->entityTypeManager = $entity_type_manager;
}
public static function create(ContainerInterface $container, $base_plugin_id) {
return new static(
$container->get('entity_type.manager')
);
}
public function getDerivativeDefinitions($base_plugin_definition) {
$this->derivatives = array();
foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
if ($entity_type->hasLinkTemplate('canonical')) {
$this->derivatives["$entity_type_id.mymodule_tab"] = [
'route_name' => "entity.$entity_type_id.mymodule",
'title' => t('Mymodule title'),
'base_route' => "entity.$entity_type_id.canonical",
'weight' => 100,
] + $base_plugin_definition;
}
}
return $this->derivatives;
}
}
3) Créez le contrôleur
Créez la classe MyModuleController dans src / Controller
namespace Drupal\mymodule\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Routing\RouteMatchInterface;
class MyModuleController extends ControllerBase {
public function doStuff(RouteMatchInterface $route_match) {
$output = [];
$parameter_name = $route_match->getRouteObject()->getOption('_mymodule_entity_type_id');
$entity = $route_match->getParameter($parameter_name);
if ($entity && $entity instanceof EntityInterface) {
$output = ['#markup' => $entity->label()];
}
return $output;
}
}