Hooks в Drupal 8

Файл хуков - THEMENAME.theme

Шаблон для страницы 404

Хук:

function НАЗВАНИЕ_ТЕМЫ_theme_suggestions_page_alter(&$suggestions, $variables, $hook) {
  // содержимое
}

Код:

            if (!is_null(Drupal::requestStack()->getCurrentRequest()->attributes->get('exception'))) {
  $status_code = Drupal::requestStack()->getCurrentRequest()->attributes->get('exception')->getStatusCode();
  switch ($status_code)
  {
      case 404: {
          $suggestions[] = 'page__' . (string) $status_code;
          break;
      }
  }
}
          
Изменение type и href у favicon

Хук:

function НАЗВАНИЕ_ТЕМЫ_page_attachments_alter(array &$page) {
  // содержимое
}

Код:

            $page['#attached']['html_head_link'][0][0]['type'] = 'image/x-icon';
    $page['#attached']['html_head_link'][0][0]['href'] = '/favicon.ico';
          
Добавление itemprop к изображению в карточке товара (Commerce)

Хук:

function НАЗВАНИЕ_ТЕМЫ_preprocess_commerce_product(&$variables) {
  // содержимое
}

Код:

            foreach ($variables['product_entity']->field_images as $key => &$image) {
  $path = $image->entity->getFileUri();
  if ($key == 0) {
      if ($variables['elements']['#view_mode'] == 'full') {
          $variables['product']['field_images'][$key]['#item_attributes']['itemprop'] = 'image';
      }
  }
}
          
Добавление itemprop к изображению в карточке товара (Node)

Хук:

function НАЗВАНИЕ_ТЕМЫ_preprocess_node(&$var) {
  // содержимое
}

Код:

            if($var['node']->getType() == 'unit_catalog' || $var['node']->getType() == 'part') {
  foreach($var['node']->field_images as $key => &$image)
  {
      if ($key == 0) {
          $var['content']['field_images'][$key]['#item_attributes']['itemprop'] = 'image';
      }
  }
}
          
Метатеги - удаление и изменение

Хук:

function НАЗВАНИЕ_ТЕМЫ_page_attachments_alter(array &$page) {
  // содержимое
}

Код:

            $unneeded_meta = ['HandheldFriendly', 'MobileOptimized', 'system_meta_generator'];
    foreach ($page['#attached']['html_head'] as $id => $attachment) {
    if (in_array($attachment[1], $unneeded_meta)) {
        unset($page['#attached']['html_head'][$id]);
    }
  }
  $viewport = array(
    '#type' => 'html_tag',
    '#tag' => 'meta',
    '#attributes' => array(
      'name' => 'viewport',
      'content' => 'width=1000',
    ),
  );
  $page['#attached']['html_head'][] = [$viewport, 'viewport'];
          

Примеры метатегов

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<meta name="viewport" content="width=1000px, initial-scale=1.0" />

Viewport для не адаптивного сайта

Хук:

function НАЗВАНИЕ_ТЕМЫ_page_attachments_alter(array &$page) {
  // содержимое
}

Код:

            $viewport = array(
  '#type' => 'html_tag',
  '#tag' => 'meta',
  '#attributes' => array(
    'name' => 'viewport',
    'content' => 'width=1024',
  ),
);
$page['#attached']['html_head'][] = [$viewport, 'viewport'];
          
Viewport для адаптивного сайта

Хук:

function НАЗВАНИЕ_ТЕМЫ_page_attachments_alter(array &$page) {
  // содержимое
}

Код:

            $viewport = array(
  '#type' => 'html_tag',
  '#tag' => 'meta',
  '#attributes' => array(
    'name' => 'viewport',
    'content' => 'width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no',
  ),
);
$page['#attached']['html_head'][] = [$viewport, 'viewport'];
          
Вывод последней ссылки в хлебных крошках для телефонов

Хук:

function НАЗВАНИЕ_ТЕМЫ_preprocess_breadcrumb(&$var) {
  // содержимое
}

Код:

            if ($variables['breadcrumb']) {
  $request = \Drupal::request();
  $route_match = \Drupal::routeMatch();
  $page_title = \Drupal::service('title_resolver')->getTitle($request, $route_match->getRouteObject());

  // ДЛЯ МОБИЛЬНОЙ ВЕРСИИ
  $variables['previous_breadcrumb'] = end($variables['breadcrumb']);
  // КОНЕЦ: ДЛЯ МОБИЛЬНОЙ ВЕРСИИ

  if (!empty($page_title)) {
    $variables['breadcrumb'][] = [
      'text' => $page_title
    ];
  }
}
$variables['#cache'] = ['max-age' => 0];
          
Вывод цены без форматирования (Commerce)

Хук:

function НАЗВАНИЕ_ТЕМЫ_preprocess_commerce_product(&$variables) {
  // содержимое
}

Код:

            $variables['price'] = (float)$variables['product_entity']->variations->entity->price->number;
          

Вывод в шаблоне:

            <meta itemprop="price" content="{{ price }}" />
          
Вывод цены без форматирования (Node)

Хук:

function НАЗВАНИЕ_ТЕМЫ_preprocess_node(&$var) {
  // содержимое
}

Код:

            $var['price_formated'] = $var['node']->field_price->value;
          

Вывод в шаблоне:

            <meta itemprop="price" content="{{ node.field_price.value }}">
          
Изменить дефолтные опции jQuery UI Dialog

Пример изменения дефолтных опций всех диалогов из своей темы:

Хук:

function НАЗВАНИЕ_ТЕМЫ_library_info_alter(&$libraries, $extension) {
  // содержимое
}

Код:

if ($extension == 'core') {
    $js_path = '/' . drupal_get_path('theme', 'THEMENAME') . '/js/jquery.ui.dialog.defaults.js';
    $libraries['jquery.ui.dialog']['js'][$js_path] = [];
  }
}

Взято из js/jquery.ui.dialog.defaults.js

jQuery.extend(jQuery.ui.dialog.prototype.options, {
  'width': 'auto',
  'modal': true,
  'closeText': Drupal.t('Close')
});
Создание и подключение своего кастомного файла twig
            use Twig\Environment;
use Twig\Loader\FilesystemLoader;

$loader = new FilesystemLoader(__DIR__ . '/templates');
$twig = new Environment($loader);
$var['myheader'] = [
  '#markup' => $twig->render('header.html.twig')
];
          
Темизация блока в конкретном регионе

В начало файла THEMENAME.theme прописать use Drupal\block\Entity\Block;

Хук:

function НАЗВАНИЕ_ТЕМЫ_theme_suggestions_block_alter(array &$suggestions, array $variables) {
  // содержимое
}

Код:

if (!empty($variables['elements']['#id'])) {
  $block = Block::load($variables['elements']['#id']);
  $suggestions[] = 'block__' . $block->getRegion();
}
return $suggestions;

В папке с темой где все шаблоны создать block--[region_name].html.twig со следующим содержимым:

            <div{{ attributes }}>
  {{ title_prefix }}
  {% if label %}
    <h3{{ title_attributes }}>{{ label }}</h3>
  {% endif %}
  {{ title_suffix }}
  {% block content %}
    {{ content }}
  {% endblock %}
</div>
          
Условие по проверки типа ноды
if($var['node']->getType() == 'МАШИННОЕ_ИМЯ_ТИПА_НОДЫ') {
  // содержимое
}
Условие по проверки ID у ноды

Хук:

function НАЗВАНИЕ_ТЕМЫ_preprocess_node(&$var) {
  // содержимое
}

Код:

if($var['node']->id() == 13) {
  // содержимое
}
Вывод классов в теге body

Хук:

function НАЗВАНИЕ_ТЕМЫ_preprocess_html(&$vars) {
  // содержимое
}

Код:

$request = \Drupal::request();

$is_front = $vars['is_front'] = \Drupal::service('path.matcher')->isFrontPage();
$is_catalog = $vars['is_catalog'] = \Drupal::service('path.current')->getPath() === '/catalog';
$is_about = $vars['is_about'] = \Drupal::service('path.current')->getPath() === '/about';
$is_in_stock = $vars['is_in_stock'] = \Drupal::service('path.current')->getPath() === '/in-stock';
$is_articles_page = $vars['is_articles_page'] = \Drupal::service('path.current')->getPath() === '/articles';
$is_customers_page = $vars['is_customers_page'] = \Drupal::service('path.current')->getPath() === '/customers';

if(!$vars['attributes']) {
  $vars['attributes'] = new \Drupal\Core\Template\Attribute();
}
if($is_front) {
  $vars['attributes']->addClass('front');
}
if($is_catalog) {
  $vars['attributes']->addClass('page-catalog');
}
if($is_about) {
  $vars['attributes']->addClass('page-about');
}
if($is_in_stock) {
  $vars['attributes']->addClass('page-in-stock');
}
if($is_articles_page) {
  $vars['attributes']->addClass('page-catalogue-useful-information');
}
if($is_customers_page) {
  $vars['attributes']->addClass('page-photo-buyers');
}
if($vars['node_type'] == 'page') {
  $vars['attributes']->addClass('КЛАСС');
}
Список хуков
function НАЗВАНИЕ_ТЕМЫ_preprocess_commerce_product(&$variables) {
  // содержимое
}

function НАЗВАНИЕ_ТЕМЫ_preprocess_node(&$var) {
  // содержимое
}

function НАЗВАНИЕ_ТЕМЫ_preprocess_block(&$var) {
  // содержимое
}