web-dev-qa-db-ja.com

キャッシュコンテキストをカスタムメニューリンクに追加するにはどうすればよいですか?

ルートパラメーターとしてユーザーを受け取る2つのルートがあり、アカウントメニューのすべてのルートにメニューリンクが必要です。 * links.menu.ymlに追加しました

client_account_links:
  deriver: \Drupal\my_module\Plugin\Menu\CustomLinks\ClientMenuLinksDerivative
  class: \Drupal\my_module\Plugin\Menu\CustomMenuLink

そして、私はmy_module/src/Plugin/MenuにCustomMenuLinkクラスを作成しました

<?php

namespace Drupal\my_module\Plugin\Menu;

use Drupal\Core\Menu\MenuLinkDefault;

/**
* A menu link that cache by user context.
*/
class CustomMenuLink extends MenuLinkDefault {

    public function getCacheMaxAge() {
        return 0;
    }

    public function getCacheContexts() {
        return ['user'];
    }
}

そして私のClientMenuLinksDerivativeは:

<?php

namespace Drupal\my_module\Plugin\Menu\CustomLinks;

use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Session\AccountProxy;
use Drupal\user\Entity\User;
use Drupal\personas\PersonaUtility;

class ClientMenuLinksDerivative extends DeriverBase implements ContainerDeriverInterface {

    protected $account;

    protected $uid;

    public function __construct(AccountProxy $current_user) {
        $this->uid = $current_user->id();
        $this->account = User::load($current_user->id());
    }

    public static function create(ContainerInterface $container, $base_plugin_id) {
        return new static(
            $container->get('current_user')
        );
    }

    public function getDerivativeDefinitions($base_plugin_definition) {
        $links = array();
        if (PersonaUtility::hasPersona($this->account, 'cliente_konsey')) {
           $links['contratos_cliente'] = [
                'title' => 'Contratos',
                'description' => 'Mis Contratos',
                'menu_name' => 'account',
                'weight' => 3,
                'route_name' => 'page_manager.page_view_mis_contratos_mis_contratos-panels_variant-0',
                'route_parameters' => ['user' => $this->uid]
            ] + $base_plugin_definition;

        $links['solicitudes_cliente'] = [
                'title' => 'Solicitudes',
                'description' => 'Mis solicitudes',
                'menu_name' => 'account',
                'weight' => 4,
                'route_name' => 'page_manager.page_view_mis_solicitudes_mis_solicitudes-panels_variant-0',
                'route_parameters' => ['user' => $this->uid]
            ] + $base_plugin_definition;
    }

    return $links;
}

}

これにより、アカウントメニューにメニューリンクが作成されますが、ルートパラメータは常に同じです。そのため、ユーザーを変更すると、リンクによって、キャッシュされる前にコードを実行する別のユーザーページに移動します。

私の質問は、ルートパラメータ(私の場合はユーザー)を使用してカスタムメニューリンクを作成する方法であり、リンクはユーザーごとに変更されますか?これは機能しないためです。また、私はhook_menu_links_discovered_alter()を試してみましたが、幸運ではありませんでした。

6
Roberto Araya

@ 4k4が言うように、この場合、派生クラスは必要ありません。次の例のようにする必要があります。

。links.menu.ymlファイル:

client_account_links:
  class: Drupal\my_module\Plugin\Menu\UserProfile
  menu_name: account
  title: 'Edit Your Profile'
  route_name:  entity.user.edit_form 

クラス:

<?php

namespace Drupal\my_module\Plugin\Menu;

use Drupal\Core\Menu\MenuLinkDefault;
use Drupal\Core\Menu\StaticMenuLinkOverridesInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Session\AccountInterface;

/**
 * Represents a menu link for a user profile edition.
 */
class UserProfile extends MenuLinkDefault {

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;


  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, StaticMenuLinkOverridesInterface $static_override, AccountInterface $current_user) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $static_override);

    $this->currentUser = $current_user;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('menu_link.static.overrides'),
      $container->get('current_user'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheContexts() {
    return ['user'];
  }

  /**
   * {@inheritdoc}
   */
  public function getRouteParameters() {
    // If the user is not Anonymous.
    if (!$this->currentUser->isAnonymous()) {
      // Getting the uid.
      $uid = $this->currentUser->id();
      // Adding the link.
      return ['user' => $uid];
    }
    return [];
  }

}
6

派生クラスは、1つのプラグインクラスの複数の派生クラスを提供するためのものです。あなたの場合、おそらく2つのバリアントしか必要ないので、OOPの方法で派生者なしでこれを行うか、yamlファイルのメニューリンクの静的な詳細を設定できます。

しかし、これらは同じ目標を達成するための異なる方法にすぎず、ここでの主な問題ではありません。

これは現在のユーザーに依存するコードだと思います。派生クラスはこのための適切な場所ではありません。これをカスタムメニューリンククラスに実装できるはずです。たとえば、動的ルートパラメータを getRouteParameters() に指定します。

public function getRouteParameters() {
  return ['user' => $this->uid];
}

次に、すでに定義したキャッシュコンテキストが機能するはずです。

public function getCacheContexts() {
    return ['user'];
}
5
4k4