web-dev-qa-db-ja.com

特定のノードのブレッドクラムを作成するにはどうすればよいですか?

ノードの前処理フックで、次のようにして現在表示されているノードのパンくずを取得しています。

_$vars['breadcrumb'] = Drupal::service('breadcrumb')
    ->build(Drupal::routeMatch())->toRenderable();
_

Drupal::routeMatch()を使用して現在のリクエストに一致するルートを取得するため、これは正常に機能します。

しかし、いくつかのノードのリストで各ノードのブレッドクラムも取得したいと考えています。この場合、現在のページではなく、リスト内の各ノードのブレッドクラムを取得したいので、Drupal::routeMatch()を使用できません。問題は、ノードオブジェクトからRouteBatchInterfaceオブジェクト(BreadcrumbBuilderが必要とする)を取得する方法が見つからないことです。 $node->urlInfo()を介してルート情報を含むURLを取得できますが、そこからルート一致に到達する方法もないようです。

これはどのように行うことができますか?

編集:

特定のノードのルート一致を取得する方法を見つけました。それが理想的な方法かどうかはわかりませんが、それで仕事が完了します。

_$routeName = $node->urlInfo()->getRouteName();
$routeParameters = $node->urlInfo()->getRouteParameters();
$route = Drupal::service('router.route_provider')->getRouteByName($routeName);
$routeMatch = new RouteMatch($routeName, $route, $routeParameters);
_

ただし、_$routeMatch_を_PathBasedBredcrumbBuilder::create_に渡しても、そのルートのブレッドクラムは生成されません。

よく見ると、組み込みのPathBasedBreadCrumbBuilderクラスは渡された_$routeMatch_パラメータを完全に無視し、代わりに、挿入されたRequestContextオブジェクトを使用してフェッチされた現在のページのパスを使用してパンくずを構築しているようです。このサービスを、渡されたパラメータを何らかの方法で使用する独自の実装と交換する必要があると思います。つづく...

2
reekris

最終的には、コアからPathBasedBredcrumbBuilderの独自のサブクラスを作成することで解決しました。このクラスはコアのバージョンとは異なり、実際には渡されたroute_matchを使用し、それに基づいてパンくずを返します。これにより、特定のノード(または他の任意のルート)のパンくずを取得できます。

(質問に示されているように)現在のノードからbuildメソッドに渡すルートの一致を計算する必要があります。 route_matchはbuildメソッドでurlオブジェクトに変換されるので少し厄介な感じがしますが、機能し、これまで考えた中で最もクリーンなソリューションです。

以下はサブクラスです:

namespace Drupal\contextual_breadcrumbs;

use Drupal\system\PathBasedBreadcrumbBuilder;
use Drupal\Core\Routing\RequestContext;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;

class ContextualPathBasedBreadcrumbBuilder extends PathBasedBreadcrumbBuilder {

    /**
    * {@inheritdoc}
    */
    public function build(RouteMatchInterface $route_match) {

      /// Set request context from passed in $route_match
      $url = Url::fromRouteMatch($route_match);
      if ($request = $this->getRequestForPath($url->toString(), [])) {
        $context = new RequestContext();
        $context->fromRequest($request);
        $this->context = $context;
      } 

      // Build breadcrumbs using new context ($route_match is unused)
      return parent::build($route_match);
    }

}
1
reekris

Service_collectorを使用して、カスタムのContextualPathBasedBreadcrumbBuilderを追加できるようです。

そのためには、モジュールservices.ymlに追加するだけです:

  my_custom_module.breadcrumb:
    class: Drupal\ my_custom_module.breadcrumb\CustomBreadcrumbBuilder
    arguments: ['@router.request_context', '@access_manager', '@router', '@path_processor_manager', '@config.factory',  '@title_resolver', '@current_user', '@path.current', '@path.matcher']
    tags:
      - { name: breadcrumb_builder, priority: 1002 }

0
Markus