Wie erstelle ich benutzerdefinierte Benutzerregisterkarten?


9

Ich versuche, eine neue benutzerdefinierte Registerkarte zu erstellen, die auf allen Routen angezeigt wird, die Nachkommen der Entität sind. {Entity_type} .canonical. Ich habe versucht, die DeriverBase-Klasse zu erweitern und dabei die Methode getDerivativeDefinitions zu überschreiben. Ich habe die Registerkarte selbst erstellt, indem ich LocalTaskDefault erweitert und die Methode getRouteParameters überschrieben habe. Die Registerkarte wird angezeigt, wenn Sie einen Standard-Drupal-Benutzerpfad wie www.mysite.com/user/1/ oder www.mysite.com/user/1/edit besuchen. Wenn wir jedoch unsere neuen benutzerdefinierten Benutzerrouten wie www.mysite.com/user/1/subscribe hinzufügen, werden keine Registerkarten angezeigt. Gibt es eine spezielle Möglichkeit, lokale Menüaufgaben auf benutzerdefinierten Routen zu definieren? Ein Beispiel des Codes:

 $this->derivatives['recurly.subscription_tab'] = [
  'title' => $this->t('Subscription'),
  'weight' => 5,
  'route_name' => 'recurly.subscription_list',
  'base_route' => "entity.$entity_type.canonical",
];

foreach ($this->derivatives as &$entry) {
  $entry += $base_plugin_definition;
}

Vielen Dank im Voraus für jede Hilfe.


Klingt sehr ähnlich zu dem, was devel mit seiner / devel route / local-Aufgabe macht. Ich schlage vor, Sie sehen sich an, wie es das implementiert.
Berdir

@Berdir das war der Ausgangspunkt, aber mir scheint immer noch etwas zu fehlen.
Tflanagan

Haben Sie versucht, die Datei 'yourmodule.links.task.yml' mit den Einstellungen für Ihre benutzerdefinierte Registerkarte hinzuzufügen?
Andrew

Antworten:


7

Wie von Berdir vorgeschlagen, können Sie sich das Devel-Modul und dessen Implementierung ansehen. Der folgende Code wurde aus Devel "extrahiert"

1) Erstellen Sie die Routen

Erstellen Sie die Datei mymodule.routing.yml in und definieren Sie einen Routenrückruf (der zum Erstellen der dynamischen Routen verwendet wird).

route_callbacks:
  - '\Drupal\mymodule\Routing\MyModuleRoutes::routes'

Erstellen Sie die Klasse MyModuleRoutes, um Ihre dynamischen Routen in src / Routing zu generieren

<?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) Erstellen Sie die dynamischen lokalen Aufgaben

Erstellen Sie die Datei mymodule.links.task.yml und definieren Sie darin einen Deriver

mymodule.tasks:
  class: \Drupal\Core\Menu\LocalTaskDefault
  deriver: \Drupal\mymodule\Plugin\Derivative\MyModuleLocalTasks

Erstellen Sie die Klasse MyModuleLocalTasks, um Ihre dynamischen Routen in src / Plugin / Derivative zu generieren

<?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) Erstellen Sie den Controller

Erstellen Sie die Klasse MyModuleController in 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;
  }

}

3
Dies war sehr ähnlich zu dem, was ich letztendlich implementiert habe. Das Übergeben des RouteMatchInterface $ route_match war die Lösung für mein Problem. Von dort stand mein Entity-Objekt meinem Controller zur Verfügung.
Tflanagan
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.