Como você implementa uma trilha de navegação?

18

Tentei definir uma nova substituição de trilha de navegação, mas ainda estou obtendo o padrão do site.

Eu criei um módulo personalizado, foo_breadcrumb:

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

Aqui está o foo_breadcrumb.services.yml:

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

Dentro src/BreadcrumbBuild.php, eu tenho:

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

Comecei a trabalhar com a única redação que pude encontrar nas migalhas de pão do Drupal 8 , mas o problema é que parece estar usando uma versão mais antiga do carregamento automático PSR-4 que não está mais no lugar (para o registro, estou na 8.0.0 -dev-beta3) e, por isso, passei a entender como todos os outros módulos funcionam na base de código.

Agora estou bastante certo de que isso está correto para carregar o módulo; no entanto, não tenho certeza se

class BreadcrumbBuild extends BreadcrumbBuilderBase

está correto. O problema é que o antigo tutorial ao qual vinculei menciona se estende BreadcrumbBuilderBase, mas os documentos mais atuais parecem não mencioná-lo e me pergunto se está desatualizado - e como devo fazer isso.

Da mesma forma, eu realmente não entendo o que o services.ymlarquivo está fazendo a esse respeito, não há documentação para isso.

njp
fonte

Respostas:

8

Sim, a trilha de navegação mudou e a documentação deve ser atualizada.

Da mesma forma, eu realmente não entendo o que o arquivo services.yml está fazendo nesse sentido, não há documentação para isso.

Para Drupal 8: O Curso Crash | DrupalCon Amsterdam 2014 , apresentação incrível, sobre 47:02:

Drupal 8 em 2 etapas:

  1. Construa uma ferramenta
  2. Ligue-o

A fiação pode variar, a abordagem é a mesma.

Como nós "conectamos" a trilha de navegação:

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

Agora precisamos contar ao sistema sobre nossa classe. Para fazer isso, definimos um novo serviço (lembra-se deles?) Referenciando nossa nova classe. Faremos isso em nosso arquivo * .services.yml, que existe exatamente para esse fim

Semelhante a um "gancho de informações" nas versões anteriores do Drupal, estamos definindo um serviço chamado mymodule.breadcrumb. Será uma instância da nossa classe de trilhas de navegação. Se necessário, poderíamos passar argumentos para o construtor de nossa classe também. É importante ressaltar que também marcamos o serviço. Os serviços etiquetados são um recurso do componente Symfony DependencyInjection especificamente e informam ao sistema para conectar automaticamente nosso construtor ao gerenciador de navegação. A prioridade especifica em que ordem os vários construtores devem ser chamados, os mais altos primeiro. Caso dois métodos apply () possam retornar true, o construtor que tiver maior prioridade será usado e o outro ignorado.

Você pode usar este código para ter como objetivo:

Estrutura (não importa muito):

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

Lembre-se de limpar o cache no final.

rpayanm
fonte
Até agora nenhuma alegria. Na verdade, copiei a taxonomia no núcleo o mais próximo possível, pois isso tinha uma implementação em funcionamento (posso chamar dpm ('Test') a partir do método apply () e ela será gerada. Mas não no meu código; nem mesmo erros intencionais de sintaxe aparecer - o que me faz suspeitar que o roteamento de serviço não é correto, mas a minha yaml é válido ... suspirar :(.
NJP
11
@njp revise o caminho da sua classe Breadcrumb (adiciono uma pasta Breadcrumb) e ela deve corresponder ao parâmetro "class" no arquivo de serviço. Também verifique todos os nomes de classe, em algum momento não corresponde a alguns arquivos ou parâmetros.
rpayanm
11
Parabéns! Uma pergunta: você "limpou o cache" após as modificações? Talvez possa ser isso.
rpayanm
11
Sim, você precisa limpar o cache, o que deve ser suficiente para atualizar os serviços. Além disso, um que vale a pena mencionar é a prioridade. O primeiro construtor que retornar TRUE de apply () vencerá; portanto, talvez seja necessário procurar outros serviços com essa tag (que é uma pesquisa fácil de texto) e verificar seu peso e implementações ().
Berdir
11
@njp, pelo contrário, a prioridade especifica em que ordem vários construtores devem ser chamados, os mais altos primeiro. Caso dois métodos apply () possam retornar true, o construtor que tiver maior prioridade será usado e o outro ignorado.
rpayanm
10

Aqui vamos nós novamente. Essas respostas estão quase certas. Uma coisa que você não pode esquecer são "tags de cache" e "contextos de cache".

Eu estava configurando um termo de taxonomia em um nó como uma trilha de navegação.

Consegui trabalhar com conselhos deste post, mas depois cliquei e notei as mesmas migalhas de pão em todas as páginas.

Para encurtar a história, certifique-se de definir alguns contextos e tags de cache.

Aqui está o meu serviço em uma essência: https://gist.github.com/jonpugh/ccaeb01e173abbc6c88f7a332d271e4a

Aqui está o meu método 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;
}
Jon Pugh
fonte
Esse problema de armazenamento em cache estava me deixando louca e muitas informações on-line em blogs etc. parecem não entender esse ponto - obrigado!
kbrinner 28/02
8

Atualização 2016 Drupal 8

A documentação afirma que você deve retornar uma instância da classe de trilha de navegação. Se você está tendo problemas para fazê-lo funcionar. aqui está a solução que funcionou para mim.

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

}

Então o arquivo yml

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

PS: se você estiver usando o bootstrap, vá para a sua /admin/appearance/settingspágina de configurações e veja as configurações da trilha de navegação. Show 'Home' breadcrumb linkdeve ser verificado. E Show current page title at enddeve ser marcado.

Depois de tudo isso, limpe seu cache. Sempre que você altera um arquivo YML, mesmo no modo de depuração, é necessário limpar o cache. você pode ir /core/rebuild.phpse ficar preso e não puder reconstruir.

Neoaptt
fonte
7

Não se esqueça do cache

O cache de renderização foi alterado bastante tarde no ciclo de desenvolvimento do D8 e, portanto, não é mencionado na série d8ftw ou nas outras respostas a esta pergunta.

A documentação da API de cache refere-se especificamente à renderização de matrizes, mas todas essas instruções se aplicam igualmente ao Breadcrumbs. As trilhas de navegação têm um toRenderable()método, o Drupal tentará armazená-las em cache no cache de renderização, e isso significa que você deve especificar informações suficientes para permitir que o Drupal faça isso corretamente.

Os detalhes estão nos documentos, mas a versão curta é a que Breadcrumbimplementa o RefinableCachableDependencyInterface. Em sua classe de construtor, convém chamar addCachableDependency()com toda e qualquer entidade ou objeto de configuração usado para construir a trilha de navegação. A documentação para 'CacheableDependencyInterface & friends' entra em mais detalhes de como e por quê.

Se houver outros contextos nos quais a trilha de navegação pode mudar, você também precisará usar manualmente addCacheContexts()para garantir que o bloco varia, addCacheTags()para garantir que a entrada do cache possa ser invalidada corretamente e mergeCacheMaxAge()se o cache é sensível ao tempo e precisa expirar.

Se isso não for feito corretamente, um dos serviços personalizados do construtor Breadcrumb será 'vencedor' e as trilhas de navegação dessa página específica serão veiculadas em todas as páginas, para todos os visitantes, para sempre.

Sean C.
fonte
4

Existe outra maneira de conseguir isso.

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

E, em seguida, crie outro arquivo na pasta de modelos do seu tema chamada "breadcrumb.html.twig" e coloque o código abaixo neste arquivo:

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

É isso aí. Agora limpe o cache e você obterá a trilha atual com o título da página atual, como Início / Título da página atual. Você pode alterar o separador substituindo "/" pelo desejado.

Sachin
fonte
2

Você deve usar um módulo contrib para adicionar o título da página atual à trilha de navegação, como Current Page Crumb: https://www.drupal.org/project/current_page_crumb

Se você quiser codificá-lo manualmente, poderá extrair o código da pasta src desse módulo. Você pode encontrar mais detalhes sobre as migalhas de pão do Drupal 8 aqui: http://www.gregboggs.com/drupal8-breadcrumbs/

Greg Boggs
fonte
É tão frustrante que algo tão simples como isso tem de exigir agarrando módulos contrib para adicioná-lo no.
Kevin
Essa é a maneira Drupal. Embora o Drupal 8 agora faça um TON no núcleo que o Drupal 7 nunca fez. Eu consertaria o núcleo do Drupal 8 migalhas de pão no núcleo, se pudesse. Mas, drush en current_page_crumbnão é tão ruim.
Greg Boggs
0

Eu tinha usado migalhas de pão personalizadas usando token no Drupal 7 e, quando esse módulo não estava disponível para o Drupal 8, acabei criando visualizações para meus tipos de conteúdo individuais usando os campos que originalmente eram os campos de token. Utilizando-o como um bloco e desativando a trilha de navegação normal. Foi um pouco mais trabalhoso do que o Breadcrumbs personalizado, mas funciona.

weben
fonte