如何创建自定义用户标签?


9

我正在尝试创建一个新的自定义标签,该标签会出现在所有实体的后代中。{entity_type} .canonical。我尝试扩展DeriverBase类,特别是重写getDerivativeDefinitions方法。我通过扩展LocalTask​​Default并覆盖getRouteParameters方法来创建选项卡。当您访问标准Drupal用户路径(例如www.mysite.com/user/1/或www.mysite.com/user/1/edit)时,将显示该选项卡。但是,当我们添加新的自定义用户路线(例如www.mysite.com/user/1/subscribe)时,不会显示任何标签。是否有一种特殊的方法可以在自定义路线上定义本地菜单任务?代码示例:

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

在此先感谢您的帮助。


听起来非常接近devel在/ devel route / local任务中所做的工作,我建议您看看它是如何实现的。
贝尔迪尔

@Berdir就是起点,但我似乎仍然缺少一些东西。
tflanagan

您是否尝试使用自定义标签的设置添加“ yourmodule.links.task.yml”文件?
Andrew

Answers:


7

根据Berdir的建议,您可以查看Devel模块及其实现方式。以下代码是从Devel中“提取”的

1)创建路线

在文件的内部和内部创建文件mymodule.routing.yml,以定义路由回调(用于创建动态路由)

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

创建类MyModuleRoutes以在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)创建动态本地任务

创建文件mymodule.links.task.yml并在其中定义派生程序

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

创建类MyModuleLocalTask​​s以在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)创建控制器

在src / Controller中创建类MyModuleController

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
这与我最终实现的目标非常相似。传递RouteMatchInterface $ route_match是解决我的问题的方法。从那里,我的实体对象可用于我的控制器。
tflanagan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.