routing
my_module.links.task.yml
my_module.my_local_task_link:
route_name: my_module.custom_route
title: "Title"
base_route: route_where.local_task.should_be_placed
13.11.2025 | Mathias Grab
How to create local task links
RouteSubscriber.php
<?php
namespace Drupal\scp_base\Routing;
use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;
class RouteSubscriber extends RouteSubscriberBase {
/**
* {@inheritdoc}
*/
protected function alterRoutes(RouteCollection $collection) {
// Make sure profile pages are not admin pages, in order to load the right
// translation.
if ($route = $collection->get('profile.user_page.single')) {
$route->setOption('_admin_route', FALSE);
}
}
}
13.11.2025 | Pascal Crott
Prevent the user profile from being displayed in backend theme using RouteSubscriber
RouteSubscriber.php
<?php
namespace Drupal\layout_builder_collapse_categories\Routing;
use Drupal\Core\Routing\RoutingEvents;
use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;
use Drupal\layout_builder_collapse_categories\Controller\ChooseBlockController;
/**
* Override the controller for layout_builder.move_block.
*/
class RouteSubscriber extends RouteSubscriberBase {
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[RoutingEvents::ALTER] = ['onAlterRoutes', -1000];
return $events;
}
/**
* {@inheritdoc}
*/
public function alterRoutes(RouteCollection $collection) {
// Add a decorator for the choose_block conroller
if ($route = $collection->get('layout_builder.choose_block')) {
$defaults = $route->getDefaults();
$route->setOption('original_controller', substr($defaults['_controller'], 0, strpos($defaults['_controller'], '::')));
$defaults['_controller'] = ChooseBlockController::class . '::build';
$route->setDefaults($defaults);
}
}
}
ChooseBlockController.php
<?php
namespace Drupal\layout_builder_collapse_categories\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\layout_builder\SectionStorageInterface;
use Drupal\Core\Controller\ControllerResolverInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ChooseBlockController extends ControllerBase {
/**
* The original ChooseBlockController
*
* @var \Drupal\layout_builder\Controller\ChooseBlockController $originalController
*/
protected $originalController;
/**
* @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
*/
public function __construct(ControllerResolverInterface $controller_resolver, RouteMatchInterface $route_match) {
$original_controller_class = $route_match->getRouteObject()->getOption('original_controller');
$this->originalController = $controller_resolver->getControllerFromDefinition($original_controller_class);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('controller_resolver'),
$container->get('current_route_match')
);
}
public function build(SectionStorageInterface $section_storage, $delta, $region) {
$build = $this->originalController->build($section_storage, $delta, $region);
foreach ($build['block_categories'] as &$category) {
if (isset($category['#open'])) {
$category['#open'] = FALSE;
}
}
return $build;
}
}
16.07.2026 | Dominik Wille