Як ви реалізуєте сухарі?


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:

Drupal 8 у 2 етапи:

  1. Побудувати інструмент
  2. Підключіть його

Електропроводка може відрізнятися, підхід однаковий.

Як ми "підключимо" панірувальний сухар:

Для http://www.palantir.net/blog/d8ftw-breadcrumbs-work :

Тепер нам потрібно розповісти системі про наш клас. Для цього ми визначаємо нову послугу (пам’ятаєте ті?) З посиланням на наш новий клас. Ми зробимо це в нашому * .services.yml файлі, який існує саме для цієї мети

Подібно до "інформаційного гачка" в попередніх версіях Drupal, ми визначаємо службу під назвою mymodule.breadcrumb. Це буде екземпляр нашого хлібного класу. Якщо потрібно, ми можемо передати аргументи і конструктору нашого класу. Важливо, що ми також тегуємо сервіс. Сервіси з тегами - це особливість компонента Symfony DependencyInjection, зокрема, і повідомляють системі автоматично підключати нашого будівельника до менеджера хлібних сухарів. Пріоритет визначає, в якому порядку слід викликати різних будівельників, найвищих перших. У випадку, якщо два застосуванні () методу можуть повернути істину, той, хто має більш високий пріоритет, буде використаний, а інший ігнорується.

Ви можете використовувати цей код для своєї мети:

Структура (не важливо багато):

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

Пам'ятайте, очистіть кеш в кінці.


Радість поки що немає. Я фактично скопіював таксономію в ядро ​​якомога ближче, оскільки це мало робочу реалізацію (я можу викликати dpm ('Test') з методу apply (), і він виведе. Але не так у моєму коді; навіть не навмисні синтаксичні помилки з'являються - що змушує мене підозрювати, що маршрутизація служби не правильна. Але мій yaml дійсний ...
зітхніть

1
@njp перегляньте шлях вашого класу Breadcrumb (я додаю папку Breadcrumb), і він повинен відповідати параметру "class" у вашому сервісному файлі. Занадто перевірити всі назви класу, колись не збігаються в якомусь файлі чи параметрах.
rpayanm

1
Вітаємо! Одне запитання: чи ви "очистили кеш" після змін? Можливо, це могло бути і так.
rpayanm

1
Так, вам потрібно очистити кеш, цього повинно вистачити для оновлення сервісів. Також пріоритетним є те, що, можливо, варто згадати. Перший конструктор, який повертає TRUE від apply (), виграє, тому вам може знадобитися пошук інших служб із цим тегом (що є простим текстовим пошуком) і перевірити їх вагу та реалізацію () реалізацій.
Бердір

1
@njp, навпаки, пріоритет визначає, в якому порядку слід викликати різних будівельників, найвищих перших. У випадку, якщо два застосуванні () методу можуть повернути істину, той, хто має більш високий пріоритет, буде використаний, а інший ігнорується.
rpayanm

10

Ось ми знову. Ці відповіді здебільшого вірні. Одне, про що ви не можете забути, - це "теги кеша" та "контексти кешу".

Я встановлював термін таксономії на вузлі як сухар.

Я отримав це, працюючи з порадами з цієї публікації, але потім я клацнув навколо і помітив однакові сухарі на кожній сторінці.

Довга коротка історія, не забудьте встановити деякі контексти та теги кешу.

Ось моя служба в суті: 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 Cache стосується конкретно массивів візуалізації, але всі ці інструкції однаково стосуються Breadcrumbs. У хлібних сухарях є toRenderable()метод, Drupal намагатиметься кешувати їх у кеш-рендері, а це означає, що ви повинні вказати достатньо інформації, щоб Drupal міг правильно це робити.

Деталі містяться в документах, але коротка версія - це те, що Breadcrumbреалізує RefinableCachableDependencyInterface. У вашому класі будівельника вам потрібно буде зателефонувати addCachableDependency()з будь-якими сутностями або об'єктами конфігурації, які використовуються для складання сухаря. Документація до "CacheableDependencyInterface & friends" детальніше описує, як і чому.

Якщо є інші контексти, в яких суха зміна може змінитися, вам також потрібно буде вручну використовувати, addCacheContexts()щоб переконатися, що блок змінюється, addCacheTags()щоб переконатися, що запис кешу може бути недійсним, а також mergeCacheMaxAge()якщо кеш залежно від часу та потребує терміну дії.

Якщо це не зроблено належним чином, одна з ваших користувальницьких служб для побудови хлібобулочних виробів буде «перемагати», а сухарі для цієї однієї конкретної сторінки будуть подаватися на кожній сторінці всім відвідувачам назавжди.


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

Це воно. Тепер очистіть кеш, і ви отримаєте сухарі з поточною назвою сторінки, як-от Головна / Поточна заголовок сторінки. Ви можете змінити роздільник, замінивши "/" на потрібний.


2

Ви повинні використовувати модуль contrib, щоб додати назву поточної сторінки до сухарі, наприклад, Поточна крихта сторінки: https://www.drupal.org/project/current_page_crumb

Якщо ви хочете ввести його в коді, ви можете витягнути його з папки src цього модуля. Докладніше про панірувальні сухарі Drupal 8 можна знайти тут: http://www.gregboggs.com/drupal8-breadcrumbs/


Це настільки засмучує, що щось таке просте, як для цього потрібно вимагати захоплення модулів для вкладки, щоб додати його.
Кевін

Такий другий шлях. Хоча Drupal 8 зараз робить TON в основному, що Drupal 7 ніколи не робив. Я б зафіксував основні сухарі Drupal 8 в ядрі, якби міг. Але, drush en current_page_crumbце не так вже й погано.
Грег Боггс

0

Я використовував власні Breadcrumbs за допомогою маркера в Drupal 7, і коли цей модуль був недоступний для Drupal 8, я в кінцевому підсумку створив представлення для моїх окремих типів вмісту, використовуючи поля, які спочатку були полями жетонів. Використання його як блоку та відключення звичайної сухарики. Це було трохи більше роботи, ніж Custom Breadcrumbs, але це працює.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.