Come si implementa un pangrattato?


18

Ho provato a definire un nuovo override breadcrumb, ma sto ancora ottenendo il sito predefinito.

Ho creato un modulo personalizzato, foo_breadcrumb:

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

Ecco il foo_breadcrumb.services.yml:

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

All'interno src/BreadcrumbBuild.php, ho:

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

Ho iniziato a lavorare sull'unico writeup che ho trovato su Drupal 8 breadcrumb , ma il fatto è che sembra che stia usando una versione precedente del caricamento automatico PSR-4 che non è più a posto (per la cronaca sono su 8.0.0 -dev-beta3), e quindi ho analizzato come funzionano tutti gli altri moduli nella base di codice.

Ora sono abbastanza sicuro che sia corretto caricare il modulo; tuttavia non sono sicuro se

class BreadcrumbBuild extends BreadcrumbBuilderBase

è corretta. Il problema è che il vecchio tutorial che ho collegato alle menzioni si estende BreadcrumbBuilderBase, ma i documenti più recenti non sembrano menzionarlo e mi chiedo se non è aggiornato - e come dovrei farlo.

Allo stesso modo, non capisco davvero cosa services.ymlstia facendo il file a questo proposito, non c'è documentazione da nessuna parte per questo.

Risposte:


8

Sì breadcrumb è cambiato e la documentazione deve essere aggiornata.

Allo stesso modo, non capisco davvero cosa stia facendo il file services.yml a questo proposito, non c'è documentazione da nessuna parte per questo.

Per Drupal 8: The Crash Course | DrupalCon Amsterdam 2014 , presentazione fantastica, 47:02 circa:

Drupal 8 in 2 passaggi:

  1. Costruisci uno strumento
  2. Collegalo

Il cablaggio può variare, l'approccio è lo stesso.

Come "cabliamo" il pangrattato:

Per http://www.palantir.net/blog/d8ftw-breadcrumbs-work :

Ora dobbiamo dire al sistema della nostra classe. Per fare ciò, definiamo un nuovo servizio (ricordi quelli?) Facendo riferimento alla nostra nuova classe. Lo faremo nel nostro file * .services.yml, che esiste esattamente per questo scopo

Simile a un "hook informativo" nelle precedenti versioni di Drupal, stiamo definendo un servizio chiamato mymodule.breadcrumb. Sarà un esempio della nostra classe di briciole di pane. Se necessario, potremmo trasmettere argomenti anche al costruttore della nostra classe. È importante sottolineare che contrassegniamo anche il servizio. I servizi con tag sono una funzionalità specifica del componente Symfony DependencyInjection e indicano al sistema di connettere automaticamente il nostro builder al gestore breadcrumb. La priorità specifica in quale ordine dovrebbero essere chiamati i vari costruttori, prima il più alto. Nel caso in cui due metodi apply () possano entrambi restituire vero, qualunque sia il costruttore che ha la priorità più alta verrà usato e l'altro ignorato.

Puoi usare questo codice per il tuo obiettivo:

Struttura (poco importa):

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

Ricorda, svuota la cache alla fine.


Nessuna gioia finora. In realtà ho copiato la tassonomia nel nucleo il più vicino possibile poiché aveva un'implementazione funzionante (posso chiamare dpm ('Test') dal metodo apply () e verrà emessa. Ma non così nel mio codice; nemmeno errori di sintassi intenzionali appare - il che mi fa sospettare che il routing del servizio non sia corretto. Ma il mio yaml è valido ... sigh :(
njp

1
@njp esamina il percorso della tua classe Breadcrumb (aggiungo una cartella Breadcrumb) e deve corrispondere al parametro "class" sul tuo file di servizio. Per controllare tutti i nomi di classe, a volte non corrispondono in alcuni file o parametri.
rpayanm,

1
Complimenti! Una domanda: hai "svuotato la cache" dopo le modifiche? Forse potrebbe essere quello.
rpayanm,

1
Sì, è necessario svuotare la cache, che dovrebbe essere sufficiente per aggiornare i servizi. Inoltre, uno che potrebbe essere degno di nota è la priorità. Il primo builder che restituisce TRUE da apply () vincerà, quindi potrebbe essere necessario cercare altri servizi con quel tag (che è una semplice ricerca di testo) e verificarne il peso e le implementazioni ().
Berdir,

1
@njp al contrario, la priorità specifica in quale ordine dovrebbero essere chiamati i vari costruttori, prima il più alto. Nel caso in cui due metodi apply () possano entrambi restituire vero, qualunque sia il costruttore che ha la priorità più alta verrà usato e l'altro ignorato.
rpayanm,

10

Ci risiamo. Queste risposte sono per lo più giuste. Una cosa che non puoi dimenticare è "tag cache" e "contesti cache".

Stavo impostando un termine di tassonomia su un nodo come briciola di pane.

L'ho fatto funzionare con i consigli di questo post, ma poi ho cliccato in giro e ho notato lo stesso pangrattato su ogni pagina.

Per farla breve, assicurati di impostare alcuni contesti e tag della cache.

Ecco il mio servizio in breve: https://gist.github.com/jonpugh/ccaeb01e173abbc6c88f7a332d271e4a

Ecco il mio metodo 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;
}

Questo problema di memorizzazione nella cache mi stava facendo impazzire e molte delle informazioni online nei blog, ecc. Sembrano perdere questo punto - grazie!
kbrinner,

8

Aggiornamento 2016 Drupal 8

La documentazione afferma che è necessario restituire un'istanza della classe breadcrumb. Se hai problemi a farlo funzionare. ecco la soluzione che ha funzionato per me.

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

}

Quindi il file yml

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

PS: se stai usando bootstrap vai alla /admin/appearance/settingspagina delle impostazioni e guarda le impostazioni breadcrumb. Show 'Home' breadcrumb linkdovrebbe essere verificato. E Show current page title at enddovrebbe essere spuntato.

Dopo tutto ciò, svuota la cache. Ogni volta che modifichi un file YML, anche in modalità debug, devi svuotare la cache. puoi andare /core/rebuild.phpse rimani bloccato e non puoi ricostruire.


7

Non dimenticare la memorizzazione nella cache

La cache di rendering è stata cambiata abbastanza tardi nel ciclo di sviluppo di D8, quindi non è menzionata nella serie d8ftw, né le altre risposte a questa domanda.

La documentazione dell'API della cache si riferisce specificamente alle matrici di rendering, ma tutte queste istruzioni si applicano ugualmente a Breadcrumb. Breadcrumb ha un toRenderable()metodo, Drupal proverà a memorizzarli nella cache di rendering e ciò significa che è necessario specificare informazioni sufficienti per consentire a Drupal di farlo correttamente.

I dettagli sono nei documenti, ma la versione breve è che Breadcrumbimplementa il file RefinableCachableDependencyInterface. Nella classe del builder, ti consigliamo di chiamare addCachableDependency()con qualsiasi entità o oggetto di configurazione utilizzato per creare il breadcrumb. La documentazione per "CacheableDependencyInterface & friends" fornisce ulteriori dettagli su come e perché.

Se ci sono altri contesti in cui il breadcrumb potrebbe cambiare, dovrai anche usare manualmente addCacheContexts()per assicurarti che il blocco vari, addCacheTags()per assicurarsi che la voce della cache possa essere invalidata correttamente e mergeCacheMaxAge()se la cache è sensibile al tempo e deve scadere.

Se ciò non viene eseguito correttamente, uno dei servizi personalizzati del builder Breadcrumb 'vincerà' e il pangrattato per quella pagina specifica verrà offerto su ogni pagina, a tutti i visitatori, per sempre.


4

C'è un altro modo per raggiungere questo obiettivo.

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

Quindi crea un altro file nella cartella del modello del tuo tema denominato "breadcrumb.html.twig" e inserisci il codice seguente in questo file:

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

Questo è tutto. Ora svuota la cache e otterrai il pangrattato con il titolo della pagina corrente come Home / Titolo pagina corrente. È possibile modificare il separatore sostituendo "/" con quello desiderato.


2

Dovresti usare un modulo contrib per aggiungere il titolo della pagina corrente al breadcrumb come Current Page Crumb: https://www.drupal.org/project/current_page_crumb

Se si desidera codificarlo manualmente, è possibile estrarre il codice dalla cartella src di quel modulo. Puoi trovare maggiori dettagli sul pangrattato Drupal 8 qui: http://www.gregboggs.com/drupal8-breadcrumbs/


È così frustrante che qualcosa di così semplice debba richiedere la raccolta di moduli contrib per aggiungerlo.
Kevin

Tale è il modo Drupal. Anche se Drupal 8 ora fa un TON nel core che Drupal 7 non ha mai fatto. Se potessi, aggiusterei il pangrattato Drupal 8 nel core. Ma drush en current_page_crumbnon è poi così male.
Greg Boggs,

0

Avevo usato il pangrattato personalizzato usando il token in Drupal 7 e quando quel modulo non era disponibile per Drupal 8 ho finito per creare viste per i miei singoli tipi di contenuto usando i campi che erano originariamente i campi token. Usandolo come blocco e disabilitando il normale pangrattato. È stato un po 'più di lavoro di Pangrattato personalizzato ma funziona.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.