パンくずリストをどのように実装しますか?


18

新しいブレッドクラムオーバーライドを定義しようとしましたが、サイトのデフォルトのままです。

foo_breadcrumbというカスタムモジュールを作成しました。

   - modules/custom/foo_breadcrumb
     - foo_breadcrumb.info.yml
     - foo_breadcrumb.services.yml
     - src/
         - BreadcrumbBuild.php

ここにありfoo_breadcrumb.services.ymlます:

services:
    foo_breadcrumb.breadcrumb:
        class: Drupal\foo_breadcrumb\BreadcrumbBuild
        tags:
            - { name: breadcrumb_builder, priority: 100 }

内部にはsrc/BreadcrumbBuild.php、私が持っています:

<?php

namespace Drupal\foo_breadcrumb;

use Drupal\Core\Breadcrumb\BreadcrumbBuilderBase;

class BreadcrumbBuild implements BreadcrumbManager {
    /**
     * {@inheritdoc}
     */
    public function applies(array $attributes) {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function build(array $attributes) {
        $breadcrumb[] = $this->l($this->t('Test'), NULL);
        $breadcrumb[] = $this->l($this->t('Test2'), 'test');
        return $breadcrumb;
    }
}
?>

Drupal 8のパンくずリスト見つけることができる唯一の記事から作業を始めましたが、実際には、もはや存在しない古いバージョンのPSR-4自動ロードを使用しているようです(8.0.0のレコードの場合) -dev-beta3)、それで私は他のすべてのモジュールがコードベースでどのように機能するかを調べました。

これで、モジュールをロードするのにこれが正しいと確信しています。しかし、私はわからない

class BreadcrumbBuild extends BreadcrumbBuilderBase

正しい。問題は、私がリンクしている言及にリンクした古いチュートリアルですBreadcrumbBuilderBaseが、最新のドキュメントでは言及していないようであり、古くなっているのかどうか、そしてどうすればいいのか疑問です。

同様に、services.ymlこの点でファイルが何をしているのか本当に理解していません。これに関するドキュメントはどこにもありません。

回答:


8

パンくずリストが変更されたため、ドキュメントを更新する必要があります。

同様に、私はservices.ymlファイルがこの点で何をしているのか本当に理解していません。これに関するドキュメントはどこにもありません。

以下のためのDrupalの8:クラッシュコース| DrupalCon Amsterdam 2014、素晴らしいプレゼンテーション、約47:02:

2ステップのDrupal 8:

  1. ツールを構築する
  2. 配線して

配線は異なる場合がありますが、アプローチは同じです。

パンくずリストを「接続」する方法:

以下のためのhttp://www.palantir.net/blog/d8ftw-breadcrumbs-work

次に、クラスについてシステムに伝える必要があります。そのために、新しいクラスを参照する新しいサービスを定義します(覚えていますか?)。まさにこの目的のために存在する* .services.ymlファイルでそれを行います

以前のバージョンのDrupalの「情報フック」と同様に、mymodule.breadcrumbという名前のサービスを定義しています。これは、パンくずリストクラスのインスタンスになります。必要に応じて、クラスのコンストラクタにも引数を渡すことができます。ただし、重要なのは、サービスにもタグを付けることです。タグ付きサービスは、特にSymfony DependencyInjectionコンポーネントの機能であり、ビルダーにブレッドクラムマネージャーに自動的に接続するようにシステムに指示します。優先順位は、さまざまなBuilderを呼び出す順序で、最も高いものを最初に指定します。2つのapply()メソッドが両方ともtrueを返す場合、優先度の高いビルダーが使用され、他のビルダーは無視されます。

目的に合わせてこのコードを使用できます。

構造(大したことではない):

- modules/custom/foo_breadcrumb
  - foo_breadcrumb.info.yml
  - foo_breadcrumb.services.yml
  - src/
    - Breadcrumb/
      - BlogBreadcrumbBuilder.php

foo_breadcrumb.services.yml:

services:
  foo_breadcrumb.breadcrumb_blog:
    class: Drupal\foo_breadcrumb\Breadcrumb\BlogBreadcrumbBuilder
    tags:
      - { name: breadcrumb_builder, priority: 100 }

BlogBreadcrumbBuilder.php:

class BlogBreadcrumbBuilder implements BreadcrumbBuilderInterface {
  use StringTranslationTrait;
  use LinkGeneratorTrait;

  /**
   * @inheritdoc
   */
  public function applies(RouteMatchInterface $route_match) {
    // This breadcrumb apply only for all articles
    $parameters = $route_match->getParameters()->all();
    if (isset($parameters['node'])) {
      return $parameters['node']->getType() == 'article';
    }
  }

  /**
   * @inheritdoc
   */
  public function build(RouteMatchInterface $route_match) {
    $breadcrumb = [Link::createFromRoute($this->t('Home'), '<front>')];
    $breadcrumb[] = Link::createFromRoute($this->t('Blog'), '<<<your route for blog>>>');
    return $breadcrumb;
  }
}

最後にキャッシュをクリアしてください。


今のところ喜びはありません。私は実際に実用的な実装を持っていたので、コアの分類を実際にできるだけコピーしました(apply()メソッドからdpm( 'Test')を呼び出すことができ、出力されます)表示-サービスルーティングが正しくないと思われますが、yamlは有効です...ため息:(
njp

1
@njpは、Breadcrumbクラスのパスを確認し(Breadcrumbフォルダーを追加します)、サービスファイルの「class」パラメーターと一致する必要があります。クラスのすべての名前を確認しすぎると、一部のファイルまたはパラメーターで一致しないことがあります。
rpayanm

1
おめでとうございます!1つの質問:変更後に「キャッシュをクリア」しましたか?おそらくそれかもしれません。
-rpayanm

1
はい、キャッシュをクリアする必要があります。サービスを更新するにはこれで十分です。また、言及する価値があるのは優先度です。apply()からTRUEを返す最初のビルダーが勝つため、そのタグを使用して他のサービスを検索し(簡単なテキスト検索)、その重みとapplys()実装を確認する必要があります。
ベルディール

1
それとは対照的に、@ njpは、さまざまなビルダーを呼び出す順序を優先順位の高いものから指定します。2つのapply()メソッドが両方ともtrueを返す場合、優先度の高いビルダーが使用され、他のビルダーは無視されます。
rpayanm

10

ああ、またか。これらの答えはほとんど正しいです。忘れられないことの1つは、「キャッシュタグ」と「キャッシュコンテキスト」です。

ノードにパンくずリストとして分類用語を設定していました。

私はこの投稿からアドバイスを受けて動作しましたが、クリックすると、すべてのページで同じパンくずリストに気付きました。

簡単に言えば、キャッシュコンテキストとタグを設定してください。

これが私のサービスです:https : //gist.github.com/jonpugh/ccaeb01e173abbc6c88f7a332d271e4a

ここに私のbuild()メソッドがあります:

/**
 * {@inheritdoc}
 */
public function build(RouteMatchInterface $route_match) {
  $node = $route_match->getParameter('node');
  $breadcrumb = new Breadcrumb();

  // By setting a "cache context" to the "url", each requested URL gets it's own cache.
  // This way a single breadcrumb isn't cached for all pages on the site.
  $breadcrumb->addCacheContexts(["url"]);

  // By adding "cache tags" for this specific node, the cache is invalidated when the node is edited.
  $breadcrumb->addCacheTags(["node:{$node->nid->value}"]);

  // Add "Home" breadcrumb link.
  $breadcrumb->addLink(Link::createFromRoute($this->t('Home'), '<front>'));

  // Given we have a taxonomy term reference field named "field_section", and that field has data,
  // Add that term as a breadcrumb link.
  if (!empty($node->field_section->entity)) {
    $breadcrumb->addLink($node->field_section->entity->toLink());
  }
  return $breadcrumb;
}

このキャッシュの問題が気になり、ブログなどのオンライン情報の多くはこの点を見逃しているようです-ありがとう!
kbrinner

8

2016 Drupal 8を更新

ドキュメントには、ブレッドクラムクラスのインスタンスを返す必要があると記載されています。うまく動かない場合。ここに私のために働いた解決策があります。

<?php

//modules/MY_MODULE/src/MyBreadcrumbBuilder.php

namespace Drupal\registration;

use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Link;

class MyBreadcrumbBuilder implements BreadcrumbBuilderInterface {

    /**
     * @inheritdoc
     */
    public function applies(RouteMatchInterface $route_match) {
        /* Allways use this. Change this is another module needs to use a new custom breadcrumb */
        return true;
        /* This code allows for only the registration page to get used by this breadcrumb
         * $parameters = explode('.', $route_match->getRouteName());
         * if ($parameters[0] === 'registration') {
         *     return true;
         * } else {
         *     return false;
         * }
         */
    }

    /**
     * @inheritdoc
     */
    public function build(RouteMatchInterface $route_match) {
        $parameters = explode('.', $route_match->getRouteName());
        $b = new Breadcrumb();
        if ($parameters[0] === 'registration') {
            /* If registration page use these links */
            $b->setLinks($this->buildRegistration($parameters[1]));
        }
        return $b;
    }

    /**
     * Creates all the links for the registration breadcrumb
     * @param type $page
     * @return type
     */
    private function buildRegistration($page) {
        return [
            Link::createFromRoute(t('Step One'), 'registration.one'),
            Link::createFromRoute(t('Step Two'), 'registration.two'),
            Link::createFromRoute(t('Step Three'), 'registration.three'),
            Link::createFromRoute(t('Step Four'), 'registration.four'),
            Link::createFromRoute(t('Step Five'), 'registration.five'),
            Link::createFromRoute(t('Step Six'), 'registration.six'),
            Link::createFromRoute(t('Step Seven'), 'registration.seven')
        ];
    }

}

次に、ymlファイル

# modules/MY_MODULE/registration/MY_MODULE.services.yml
services:
  registration.breadcrumb:
    class: Drupal\registration\MyBreadcrumbBuilder
    tags:
      - { name: breadcrumb_builder, priority: 100 }

PS:ブートストラップを使用している場合は、/admin/appearance/settings設定ページに移動してパンくずリストの設定を確認してください。Show 'Home' breadcrumb linkオンにする必要があります。そして、Show current page title at endオフチェックする必要があります。

これがすべて完了したら、キャッシュをクリアします。デバッグモードであっても、YMLファイルを変更するたびに、キャッシュをクリアする必要があります。あなたが/core/rebuild.php動けなくなって再構築できない場合に行くことができます。


7

キャッシングを忘れないでください

レンダーキャッシュはD8開発サイクルのかなり後期に変更されたため、d8ftwシリーズやこの質問に対する他の回答では言及されていません。

キャッシュAPIのドキュメントでは、配列をレンダリングするために、具体的言及はなく、それらの命令の全ては、ブレッドクラムにも同様に適用されます。パンくずリストにはtoRenderable()メソッドがあり、Drupalはそれらをレンダーキャッシュにキャッシュしようとするため、Drupalが適切に実行できるように十分な情報を指定する必要あります。

詳細はドキュメントにありますが、短いバージョンはをBreadcrumb実装したものRefinableCachableDependencyInterfaceです。ビルダークラスではaddCachableDependency()、パンくずリストの作成に使用されるすべてのエンティティまたは構成オブジェクトを使用して呼び出します。 「CacheableDependencyInterface&friends」のドキュメントでは、方法と理由の詳細を説明しています。

パンくずリストが変更される可能性のある他のコンテキストがある場合は、手動で使用addCacheContexts()してブロックが変化addCacheTags()することを確認し、キャッシュエントリを正しく無効化できることを確認しmergeCacheMaxAge()、キャッシュが時間依存で期限切れになる必要があるかどうかを確認する必要があります。

これが適切に行われないと、カスタムBreadcrumb Builderサービスの1つが「勝ち」、その特定のページのブレッドクラムがすべてのページで、すべての訪問者に永久に提供されます。


4

これを実現する別の方法があります。

/**
 * Implements hook_preprocess_breadcrumb().
 */
 function theme_name_preprocess_breadcrumb(&$variables){
  if(($node = \Drupal::routeMatch()->getParameter('node')) && $variables['breadcrumb']){
    $variables['breadcrumb'][] = array(
     'text' => $node->getTitle() 
   );
  }
}

次に、テーマのテンプレートフォルダに「breadcrumb.html.twig」という名前の別のファイルを作成し、このファイルに以下のコードを配置します。

{% if breadcrumb %}
  <nav class="breadcrumb" role="navigation" aria-labelledby="system-breadcrumb">
    <h2 id="system-breadcrumb" class="visually-hidden">{{ 'Breadcrumb'|t }}</h2>
    <ul>
    {% for item in breadcrumb %}
      <li>
        {% if item.url %}
          <a href="{{ item.url }}">{{ item.text }}</a>
        {% else %}
          {{ item.text }}
        {% endif %}
      </li> /
    {% endfor %}
    </ul>
  </nav>
{% endif %}

それでおしまい。キャッシュをフラッシュすると、Home / Current Page Titleなどの現在のページタイトルでブレッドクラムが表示されます。「/」を目的の区切り文字に置き換えることにより、区切り文字を変更できます。


2

contribモジュールを使用して、Current Page Crumbなどの現在のページタイトルをブレッドクラムに追加する必要があります。https//www.drupal.org/project/current_page_crumb

手動でコーディングしたい場合は、そのモジュールのsrcフォルダーからコードをプルできます。Drupal 8ブレッドクラムの詳細については、http//www.gregboggs.com/drupal8-breadcrumbs/をご覧ください。


とてもイライラして、これほど簡単なものを追加するには、contribモジュールをつかむ必要があります
ケビン

これがDrupalの方法です。Drupal 8は、Drupal 7が一度も実行したことのないTONをコアで実行します。可能であれば、コアのコアDrupal 8ブレッドクラムを修正します。しかし、drush en current_page_crumbそれほど悪くはありません。
グレッグボッ

0

Drupal 7でトークンを使用してカスタムパンくずリストを使用していましたが、そのモジュールがDrupal 8で使用できない場合、元々トークンフィールドであったフィールドを使用して個々のコンテンツタイプのビューを作成することになりました。ブロックとして使用し、通常のブレッドクラムを無効にします。これは、カスタムパンくずリストよりも少し多くの作業でしたが、機能します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.