nerdfisch: DevBits

Kleine, aber feine Code-Snippets, nützliche Tweaks und elegante Lösungsansätze aus dem Entwickler-Alltag

13.11.2025 | Mathias Grab

How to create local task links

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
yml / yaml
local task links
routing
13.11.2025 | Nikolas Kopp

Clear APC & Opcache

clear_cache.php
<?php

apcu_clear_cache();
opcache_reset();
php
drush
Drush
caching
cache
Debugging
debugging
debug
13.11.2025 | Nikolas Kopp, Pascal Crott

Token Chaining – How to access tokens for nested information

my_group.module
/**
 * Implements hook_tokens().
 */
function example_group_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
  $replacements = [];

  // Automatically expose related entities to group_relationships.
  if ($type == 'group_relationship' && !empty($data[$type])) {
    $token_service = \Drupal::token();

    /** @var \Drupal\example\GroupRelationshipTypeServiceInterface $group_relationship_type_service */
    $group_relationship_type_service = \Drupal::service('example.group_relationship_type_service');

    $group_relationship = $data['group_relationship'];
    assert($group_relationship instanceof GroupRelationshipInterface);

    foreach ($tokens as $name => $original) {
      /** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
      foreach ($group_relationship_type_service->getConfiguredEntityTypes() as $entity_type_id => $entity_type) {
        if ($name == $entity_type_id) {
          $entity = $group_relationship->getEntity();
          $bubbleable_metadata->addCacheableDependency($entity);
          $replacements[$original] = $entity->label();
        }

        // Actual chaining of tokens handled below.
        if ($entity_tokens = $token_service->findWithPrefix($tokens, $entity_type_id)) {
          $replacements += $token_service->generate($entity_type_id, $entity_tokens, [$entity_type_id => $group_relationship->getEntity()], $options, $bubbleable_metadata);
        }
      }
    }
  }

  return $replacements;
}
module
token
group
group
13.11.2025 | Nikolas Kopp

Cache Debugging for Render Elements

development.services.yml
  renderer.config:
    required_cache_contexts: ['languages:language_interface', 'theme', 'user.permissions']
    auto_placeholder_conditions:
      max-age: 0
      contexts: ['session', 'user']
      tags: []
    debug: true # The debug setting
caching
debug
debugging
Debugging
13.11.2025 | Pascal Crott

Prevent the user profile from being displayed in backend theme using RouteSubscriber

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);
    }
  }

}
php
user
theme
themes
backend
routing
routing
UX