Перейти к основному содержанию

Вывод терминов таксономии со списком связанных нод

Вывод плоской таксономии.

Отлично реализуется через views. 

  1. Создаем обычное представление.
    Показать Содержимое с нужным типом
  2. Вид отображения: Поля.
    Добавляем нужные поля.
    Добавляем поле содержимого с термином таксономии (Исключить из вывода: Да)
  3. В разделе "Формат - настройки" в Группирующее поле Nr.1 выставляем поле с термином таксономии.
     


У меня получилось на выходе: 

 

Вывод одноуровневой иерархии 

Через связку Views tree и Views Field View.

Стандартный модуль Views Tree не совсем подходит. Проблема в том, что Views Tree работает по принципу «одна строка — один элемент дерева». Когда добавляется связь с нодами, Views начинает дублировать строки терминов для каждой ноды или схлопывать их, что ломает иерархию дерева.
Чтобы вывести все ноды под каждым термином в иерархическом дереве, лучше всего использовать связку: Views Tree (для структуры терминов) + Views Field View (для вывода списка нод).

Шаг 1. Создаем «Вложенное» представление (Child View)
Это представление будет отвечать только за вывод списка нод для одного конкретного термина.

  • Создаем новое View (тип: Содержимое/Nodes).
  • Создаем дисплей типа Embed (Вставка).
  • Добавляем Контекстный фильтр: Содержимое: Has taxonomy term ID.
    В настройках фильтра выбираем: «Provide default value» -> «Taxonomy term ID from URL» (хотя передавать мы его будем вручную).
    Настроиваем нужные для отображения поля (заголовок ноды, ссылка и т.д.).

Шаг 2. Настраиваем «Основное» view (Parent View)
Здесь мы строим дерево таксономии с помощью Views Tree.

  • Создаем новое View (тип: Термины таксономии  типа наш словарь).
  • Добавляем поля
    1. Добавляем поле ID термина (Идентификатор tid термина таксономии).
      Исключить из вывода: Да.
    2. Добавляем поле Родители Термина (Родительский термин термина. Это может привести к дублирующим записям, если вы используете словарь, который позволяет нескольких родителей.)
      Исключить из вывода: Да.
      Форматер - Идентификатор сущности.
    3. Добавляем поле Просмотр    Глобальный    (Embed a view as a field. This can cause slow performance, so enable some caching).
      Просмотр - выбираем дочернее представление, созданное на шаге 1.
      Отображение - если сразу выставить Embed друпал выдаст ошибку. Оставляем default.
      В контекстные фильтры пишем {{ raw_fields.tid }}. Посмотреть заполнитель можно в разделе Подстановочные шаблоны.
      Сохраняем.
    4. Снова открываем поле Просмотр    Глобальный . 
      В разделе Отображение выставляем Embed.

  • В разделе настройки представления Формат выбираем Tree (list)
  • Открываем настройки выбранного формата.
    В настройке Main field выбираем поле с tid термина
    В настройке Parent tid выбираем поле Родители термина


     

    Итоговое отображение

 

Через views и тему сайта (не рекомендуется).

Шаг 1. Создаем «Вложенное» представление (Child View). Как делали до этого.

Шаг 2. Создаем пустую страницу. Выставляем alias страницы. В моем случае это /resources2

Шаг 3. В своей теме сайта:

/**
 * Implements hook_preprocess_page().
 */
function your_theme_preprocess_page(&$variables) {    // <-- вписать название своей темы

  // Получаем текущий путь
  $current_path = \Drupal::service('path.current')->getPath();
  $alias = \Drupal::service('path_alias.manager')->getAliasByPath($current_path);

  // Проверяем по алиасу, а не по системному пути
  if ($alias === '/resources2') {   // <-- заменить на нужный алиас
    $tree = \Drupal::entityTypeManager()
      ->getStorage('taxonomy_term')
      ->loadTree('link_area');         // <-- заменить на нужный словарь

    $items = [];
    foreach ($tree as $item) {
      /** @var \Drupal\taxonomy\TermInterface $term */
      $term = \Drupal::entityTypeManager()
        ->getStorage('taxonomy_term')
        ->load($item->tid);

      // Вложенные ссылки
      $links_view = views_embed_view('category_links', 'embed_1', $item->tid);    // <-- заменить имя представления и название вида

      $items[] = [
        'name' => $term->label(),
        'url' => $term->toUrl()->toString(),
        'depth' => $item->depth,
        'links' => $links_view,
      ];
    }

    $variables['link_category_tree'] = $items;
  }
}

function your_theme_theme_suggestions_page_alter(array &$suggestions, array $variables) {    // <-- вписать название своей темы
  $current_path = \Drupal::service('path.current')->getPath();
  $alias = \Drupal::service('path_alias.manager')->getAliasByPath($current_path);

  if ($alias === '/resources2') {    // <-- заменить на нужный алиас
    $suggestions[] = 'page__resources2';    // <-- заменить на нужный алиас
  }
}


Шаг 4. Добавить шалон для страницы. 
Скопируем page.html.twig в page--resources2.html.twig

<!-- заменяем {{ page.content }} на наш код -->
{% if link_category_tree %}
    <div class="resources-tree">
      <ul class="category-tree">
        {% for item in link_category_tree %}
          <li style="margin-left: {{ item.depth * 20 }}px;">
            <a href="{{ item.url }}">{{ item.name }}</a>
            {% if item.links %}
              <div class="category-links">{{ item.links }}</div>
            {% endif %}
          </li>
        {% endfor %}
      </ul>
    </div>
  {% endif %}


Шаг 5. Чистим кеш. 
Открываем страницу /resources2 - должен отобразиться список терминов с нодами.
 

Через views и кастомный модуль (рекомендуется).

Шаг 1. Создаем «Вложенное» представление (Child View). Как делали до этого.
Шаг 2. Создаем кастомный модуль
Например: my_resources
Папка: modules/custom/my_resources

Путь страницы в моем случае будет /resources3

Файлы:

  1. my_resources.info.yml

    name: My Resources
    type: module
    description: 'Страница ресурсов с деревом категорий'
    core_version_requirement: ^10.3 || ^11
    package: Custom
  2. my_resources.routing.yml

    my_resources.page:
      path: '/resources3'    # <-- заменить на свой
      defaults:
        _controller: '\Drupal\my_resources\Controller\ResourcesController::build'
        _title: 'Ресурсы'
      requirements:
        _access: 'TRUE'
  3. src/Controller/ResourcesController.php

    <?php
    
    namespace Drupal\my_resources\Controller;
    
    use Drupal\Core\Controller\ControllerBase;
    use Drupal\Core\Cache\CacheableResponse;
    use Drupal\taxonomy\TermInterface;
    
    class ResourcesController extends ControllerBase {
    
      public function build() {
        $tree = $this->entityTypeManager()
          ->getStorage('taxonomy_term')
          ->loadTree('link_area');    // <-- заменить на нужный словарь
    
        $items = [];
        foreach ($tree as $item) {
          $term = $this->entityTypeManager()
            ->getStorage('taxonomy_term')
            ->load($item->tid);
    
          $links_view = views_embed_view('category_links', 'embed_1', $item->tid);    // <-- заменить имя представления и имя вида
    
          $items[] = [
            'name' => $term->label(),
            'url' => $term->toUrl()->toString(),
            'depth' => $item->depth,
            'links' => $links_view,
          ];
        }
    
        $build = [
          '#theme' => 'my_resources_tree',
          '#items' => $items,
          '#cache' => [
            'tags' => ['taxonomy_term_list:link_area'],    // <-- заменить на нужный словарь
            'contexts' => ['url.path'],
          ],
        ];
    
        return $build;
      }
    }
  4. templates/my-resources-tree.html.twig (опционально)

    <div class="resources-tree">
      <ul class="category-tree">
        {% for item in items %}
          <li style="margin-left: {{ item.depth * 20 }}px;">
            <a href="{{ item.url }}">{{ item.name }}</a>
            {% if item.links %}
              <div class="category-links">{{ item.links }}</div>
            {% endif %}
          </li>
        {% endfor %}
      </ul>
    </div>
  5. Регистрируем шаблон (если создавали в пункте 4) в my_resources.module

    <?php
    
    /**
     * @file
     * Hooks for My Resources module.
     */
    
    /**
     * Implements hook_theme().
     */
    function my_resources_theme($existing, $type, $theme, $path) {
      return [
        'my_resources_tree' => [
          'variables' => ['items' => []],
          'template' => 'my-resources-tree',
        ],
      ];
    }
  6. Включаем модуль в админке. Переходим на страницу /resources3