Wie setzt man einen Breadcrumb um?

18

Ich habe versucht, einen neuen Breadcrumb-Override zu definieren, erhalte jedoch weiterhin die Site-Standardeinstellung.

Ich habe ein benutzerdefiniertes Modul erstellt, foo_breadcrumb:

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

Hier ist der foo_breadcrumb.services.yml:

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

Innen habe src/BreadcrumbBuild.phpich:

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

Ich habe angefangen, die einzige Beschreibung zu bearbeiten, die ich für Drupal 8 finden konnte , aber es scheint, dass eine ältere Version des PSR-4-Autoloadings verwendet wird, die nicht mehr vorhanden ist (für den Rekord bin ich auf 8.0.0 -dev-beta3), und so ging ich davon aus, wie alle anderen Module in der Codebasis funktionieren.

Jetzt bin ich mir ziemlich sicher, dass dies korrekt ist, um das Modul zum Laden zu bringen. Ich bin mir jedoch nicht sicher, ob

class BreadcrumbBuild extends BreadcrumbBuilderBase

ist richtig. Das Problem ist, dass das alte Tutorial, von dem ich auf Erwähnungen BreadcrumbBuilderBaseverweise, nicht mehr erwähnt wird, und ich frage mich, ob es veraltet ist - und wie ich das tun soll.

Ebenso verstehe ich nicht wirklich, was die services.ymlDatei in dieser Hinsicht tut, es gibt dafür nirgendwo Dokumentation.

njp
quelle

Antworten:

8

Yeah Breadcrumb geändert und die Dokumentation muss aktualisiert werden.

Ebenso verstehe ich nicht wirklich, was die services.yml-Datei in dieser Hinsicht tut, es gibt dafür nirgendwo Dokumentation.

Für Drupal 8: Der Crashkurs | DrupalCon Amsterdam 2014 , tolle Präsentation, ungefähr 47:02:

Drupal 8 in 2 Schritten:

  1. Erstellen Sie ein Tool
  2. Verdrahten Sie es

Die Verkabelung kann variieren, der Ansatz ist der gleiche.

So "verdrahten" wir den Breadcrumb:

Für http://www.palantir.net/blog/d8ftw-breadcrumbs-work :

Jetzt müssen wir dem System von unserer Klasse erzählen. Dazu definieren wir einen neuen Service (merken Sie sich diese?), Der auf unsere neue Klasse verweist. Das machen wir in unserer * .services.yml-Datei, die genau zu diesem Zweck existiert

Ähnlich wie bei einem "Info-Hook" in früheren Drupal-Versionen definieren wir einen Service mit dem Namen mymodule.breadcrumb. Es wird eine Instanz unserer Breadcrumb-Klasse sein. Bei Bedarf könnten wir auch Argumente an den Konstruktor unserer Klasse übergeben. Wichtig ist jedoch, dass wir den Service auch kennzeichnen. Getaggte Services sind eine Funktion der Symfony DependencyInjection-Komponente und weisen das System an, unseren Builder automatisch mit dem Breadcrumb-Manager zu verbinden. Die Priorität gibt an, in welcher Reihenfolge verschiedene Builder aufgerufen werden sollen, die höchste zuerst. Wenn zwei apply () -Methoden true zurückgeben, wird der Builder mit der höheren Priorität verwendet und der andere ignoriert.

Sie können diesen Code für Ihr Ziel verwenden:

Struktur (nicht viel ausmachen):

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

Denken Sie daran, den Cache am Ende zu leeren.

rpayanm
quelle
Bisher keine Freude. Eigentlich habe ich die Taxonomie im Kern so genau wie möglich kopiert, da dies eine funktionierende Implementierung hatte (ich kann dpm ('Test') von der Methode applic () aufrufen und sie ausgeben. Aber nicht so in meinem Code, nicht einmal absichtliche Syntaxfehler erscheint - was mich vermuten lässt, dass das Service-Routing nicht korrekt ist. Aber mein Yaml ist gültig ...
seufz
1
@njp überprüfe den Pfad deiner Breadcrumb-Klasse (ich füge einen Ordner Breadcrumb hinzu) und er muss mit dem "class" -Parameter deiner Servicedatei übereinstimmen. Zu prüfen, ob alle Klassennamen vorhanden sind, stimmen einige Dateien oder Parameter manchmal nicht überein.
rpayanm
1
Glückwunsch! Eine Frage: Haben Sie nach den Änderungen den Cache "geleert"? Vielleicht könnte es das sein.
rpayanm
1
Ja, Sie müssen den Cache leeren. Dies sollte ausreichen, um die Dienste zu aktualisieren. Erwähnenswert ist auch die Priorität. Der erste Builder, der TRUE von applic () zurückgibt, wird gewinnen. Daher müssen Sie möglicherweise nach anderen Diensten mit diesem Tag suchen (dies ist eine einfache Textsuche) und deren Gewichtung und Implementierungen von applic () überprüfen.
Berdir
1
@njp im Gegenteil, die Priorität gibt an, in welcher Reihenfolge verschiedene Builder aufgerufen werden sollen, am höchsten zuerst. Wenn zwei apply () -Methoden true zurückgeben, wird der Builder mit der höheren Priorität verwendet und der andere ignoriert.
rpayanm
10

Jetzt geht das schon wieder los. Diese Antworten sind größtenteils richtig. Eine Sache, die Sie nicht vergessen dürfen, sind "Cache-Tags" und "Cache-Kontexte".

Ich habe einen Taxonomiebegriff auf einem Knoten als Breadcrumb eingerichtet.

Ich habe es mit Ratschlägen aus diesem Beitrag zum Laufen gebracht, aber dann habe ich mich umgesehen und auf jeder Seite die gleichen Brotkrumen bemerkt.

Kurz gesagt, stellen Sie sicher, dass Sie einige Cache-Kontexte und -Tags festlegen.

Hier ist mein Service in Kürze: https://gist.github.com/jonpugh/ccaeb01e173abbc6c88f7a332d271e4a

Hier ist meine build () Methode:

/**
 * {@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;
}
Jon Pugh
quelle
Dieses Caching-Problem hat mich wahnsinnig gemacht und viele Informationen in Blogs usw. scheinen diesen Punkt zu verfehlen - danke!
kbrinner
8

Update 2016 Drupal 8

In der Dokumentation wird angegeben, dass Sie eine Instanz der Breadcrumb-Klasse zurückgeben müssen. Wenn Sie Probleme haben, es zum Laufen zu bringen. Hier ist die Lösung, die für mich funktioniert hat.

<?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')
        ];
    }

}

Dann die yml-Datei

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

PS: Wenn Sie Bootstrap verwenden, gehen Sie zu Ihrer /admin/appearance/settingsEinstellungsseite und sehen Sie sich die Breadcrumb-Einstellungen an. Show 'Home' breadcrumb linksollte aktiviert sein. Und Show current page title at endsollte abgehakt werden.

Nachdem dies erledigt ist, leeren Sie Ihren Cache. Jedes Mal, wenn Sie eine YML-Datei ändern, müssen Sie auch im Debug-Modus den Cache leeren. Sie können zu gehen, /core/rebuild.phpwenn Sie nicht weiterkommen und nicht wieder aufbauen können.

Neoaptt
quelle
7

Caching nicht vergessen

Der Render-Cache wurde relativ spät im D8-Entwicklungszyklus geändert und wird daher in der d8ftw-Reihe oder den anderen Antworten auf diese Frage nicht erwähnt.

Die Cache-API-Dokumentation bezieht sich speziell auf das Rendern von Arrays, alle diese Anweisungen gelten jedoch auch für Breadcrumbs. Breadcrumbs haben eine toRenderable()Methode. Drupal wird versuchen, sie im Render-Cache zwischenzuspeichern. Das bedeutet, dass Sie genügend Informationen angeben müssen , damit Drupal dies ordnungsgemäß ausführen kann.

Die Details sind in den Dokumenten enthalten, aber die Kurzversion Breadcrumbimplementiert die RefinableCachableDependencyInterface. In Ihrer Builder-Klasse möchten Sie addCachableDependency()mit allen Entitäten oder Konfigurationsobjekten aufrufen , die zum Erstellen des Breadcrumbs verwendet werden. In der Dokumentation zu 'CacheableDependencyInterface & friends' wird detaillierter beschrieben, wie und warum.

Wenn es andere Kontexte gibt, in denen sich der Breadcrumb ändern könnte, müssen Sie ihn auch manuell verwenden addCacheContexts(), um sicherzustellen, dass der Block variiert, addCacheTags()der Cache-Eintrag korrekt ungültig gemacht werden kann und mergeCacheMaxAge()wenn der Cache zeitkritisch ist und verfallen muss.

Wenn dies nicht ordnungsgemäß durchgeführt wird, wird einer Ihrer benutzerdefinierten Breadcrumb-Builder-Services "gewinnen", und die Breadcrumbs für diese eine bestimmte Seite werden auf jeder Seite für alle Besucher für immer bereitgestellt.

Sean C.
quelle
4

Es gibt einen anderen Weg, dies zu erreichen.

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

Erstellen Sie anschließend eine weitere Datei im Vorlagenordner Ihres Themas mit dem Namen "breadcrumb.html.twig" und fügen Sie den folgenden Code in diese Datei ein:

{% 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 %}

Das ist es. Leeren Sie nun den Cache und Sie erhalten einen Breadcrumb mit dem aktuellen Seitentitel wie Startseite / Aktueller Seitentitel. Sie können das Trennzeichen ändern, indem Sie "/" durch das gewünschte ersetzen.

Sachin
quelle
2

Sie sollten ein Contrib-Modul verwenden, um den aktuellen Seitentitel zum Breadcrumb hinzuzufügen, z. B. Current Page Crumb: https://www.drupal.org/project/current_page_crumb

Wenn Sie den Code manuell codieren möchten, können Sie ihn aus dem src-Ordner dieses Moduls abrufen. Weitere Informationen zu Drupal 8 finden Sie hier: http://www.gregboggs.com/drupal8-breadcrumbs/

Greg Boggs
quelle
Es ist so frustrierend, dass für so etwas Einfaches ergreifende Contrib-Module erforderlich sind, um es hinzuzufügen.
Kevin
Das ist der Drupal-Weg. Obwohl Drupal 8 jetzt eine TON im Kern hat, die Drupal 7 nie hat. Ich würde Kern Drupal 8 Brotkrumen im Kern reparieren, wenn ich könnte. Aber drush en current_page_crumbist nicht so schlimm.
Greg Boggs
0

Ich hatte in Drupal 7 benutzerdefinierte Brotkrumen mit Token verwendet und als dieses Modul für Drupal 8 nicht verfügbar war, erstellte ich Ansichten für meine einzelnen Inhaltstypen mithilfe der Felder, die ursprünglich die Tokenfelder waren. Verwenden Sie es als Block und deaktivieren Sie den normalen Breadcrumb. Es war ein bisschen mehr Arbeit als Custom Breadcrumbs, aber es funktioniert.

weben
quelle