Программно выводим нужное меню в Drupal 8.
Если вам понадобится вывести меню программно, на странице или еще где, да даже просто получить пункты меню, то так просто как в Drupal 7 уже не выйдет. Вот два варианта вывода меню.
// ЗАМЕТКА: Получить список всех меню: menu_ui_get_menus();
// Импортируем необходимый класс.
use Drupal\Core\Menu\MenuTreeParameters;
// Создаем объект с настройками.
// Он имеет свои настройки, например минимальный и максимальный уровень
// вложения.
// Подробнее: https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Menu!MenuTreeParameters.php/class/MenuTreeParameters/8
$menu_tree_parameters = new MenuTreeParameters();
// Загружаем меню с параметрами. Название меню здесь: main.
$tree = \Drupal::menuTree()->load('main', $menu_tree_parameters);
// Преобразуем меню в renderable array.
$tree_array = \Drupal::menuTree()->build($tree);
// Рендерим меню и получаем html ul список. Он будет сгенерирован с
// использованием шаблона по умолчанию для Drupal 8.
$menu = drupal_render($tree_array);
echo $menu; // вывод.
Продвинутый способ
Данный способ я назвал продвинутым, так как в нем я покажу пример, как можно определить свой шаблон для меню. Этот раздел больше пригодиться тем кто понимает что и куда отсюда вставлять.
/**
* Implements hook_theme().
*
* Объявляем наш темплейт через который будет прогоняться меню.
* Тут ничего нет нового для тех кто ранее уже использовал данный хук.
* Всё это на примере темы, использование в своём модуле может немного
* отличаться.
*/
function MYTHEME_theme() {
return array(
// Объявляем название нашего темплейта.
'my_custom_menu_template' =?> array(
// Объявляем какие переменные принимает темплейт.
'variables' => array(
'items' => NULL,
),
// Объявляем название файла-шаблона. html.twig указывать не нужно.
'template' => 'my-custom-menu-template',
),
);
}
Создаем шаблон
Теперь нам надо в папке templates создать шаблон * my-custom-menu-template.html.twig* со следующим содержимым.
{% import _self as menus %}
{{ menus.menu_links(items, attributes, 0) }}
{% macro menu_links(items, attributes, menu_level) %}
{% import _self as menus %}
{% if items %}
{% if menu_level == 0 %}
<ul>
{% else %}<ul class="submenus"><li>
{% endif %}
{% for item in items %}
</li><li item.attributes="">
{{ link(item.title, item.url) }}
{% if item.below %}
{{ menus.menu_links(item.below, attributes, menu_level + 1) }}
{% endif %}
{% endfor %}
</li>{{></ul>
{% endif %}
{% endmacro %}
</ul>{{>
Это слегка модифицированный пример оригинального темплейта, который вы можете найти в /core/modules/system/templates/menu.html.twig. Тут для вложенного меню добавлен класс submenu.
Выводим меню
Вывод от стандартного будет отличаться лишь тем, что мы изменим шаблон.
use Drupal\Core\Menu\MenuTreeParameters;
$menu_tree_parameters = new MenuTreeParameters();
$tree = \Drupal::menuTree()-?>load('main', $menu_tree_parameters);
$tree_array = \Drupal::menuTree()->build($tree);
// Меняем тему на нашу.
$tree_array['#theme'] = 'my_custom_menu_template';
$menu = drupal_render($tree_array);
echo $menu; // вывод.
Теперь меню будет прогоняться через наш темплейт и мы можем контролировать классы и разметку.
Комментарии
Привет.
На 8-ке делать сейчас НИКАКОГО смысла и причины нет. Я с 8-кой уже достаточно неплохо познакомился и могу с уверенностью сказать, даже если вы найдете исполнителя\студию которая вам сделает это, вам придется минимум одного разработчика брать в штат или на поддержку причем чуть ли, опять же, не постоянную. Постоянно придется править все, редактировать и т.д. А так как таких разрабов, кто знает 8-ку отлично, очень мало, и основная масса это разработчики ядра, то стоимость будет космическая. Делайте на 7-ке и не парьтесь, просто заказывайте так, чтобы вам делали максимально совместимо с 8-кой, чтобы было проще мигрировать в дальнейшем. Например, вместо node reference, использовать entity reference, который в ядре 8-ки и т.д. Уже многие модули для 7-ки пишутся и под 8-ку, старайтесь отдавать предпочтение подобным, ибо с большой вероятностью будет миграционный патч, ну как минимум модуль будет и можно ручками перенести. 7-ка будет поддерживаться около 3-ёх лет после релиза 8-ки, которая раньше лета 2015, скорее всего, не релизнится. 3 года для сайта это приличный срок, это отметка когда НУЖНО делать ребрендинг, если он не делался ранее, и все делать под текущие реалии. В этот момент и можно будет сьехать на 8-ку, либо сделать аналог с нуля (если контента не так много будет).
TL;DR - берите 7-ку и не рискуйте своими деньгами с 8-кой. 8-ку имеет смысл заказывать, как минимум, после релиза, а в лучшем случае через пол года после релиза. В общем эту затею можно смело оттягивать на 1 год.
P.s. Даже банально я, портанув Mappy на 8-ку нашел, как мне показалось, нерпавильную логику работы этой саймой 8-ки и API. Написал ишью, месяц никто там реагировал, а сейчас там статус Critical и проблему решают на уровне ядра, и это заденет API. В случае с найденной мной ошибкой, вероятнее всего контриб модулей это не коснется, решится на уровне ядра, а таких критикалов сейчас много и некоторые скорее всего еще сломают API и это доработки\переделки вашего сайта, а это доп. расходы, причем не маленькие.
Ок, понятно. Спасибо за развёрнутый ответ!
Никита спасибо за статью. Буду благодарен если подскажете. На Drupal 8 я столкнулся с проблемой -
мне нужно в навигации по сайту в шапке, добавить по бокам кнопок, картинку. чтобы li в main_menu, были с двух сторон с картинками.
В Drupal 7 я взял за основу тему ZEN и это реализовал так -
а в Drupal 8 взял тему Basic нашел там файл menu.html.twig в нем попытался поменять шаблон. но когда стал менять у меня это стало влиять не только на верхнее меню, но и другие меню которые были на странице.
Не подскажете как сделать чтобы сделать шаблон только для Primary menu или main menu.
Я в принципе решил данную проблему отключив блок меню в футере, и кажется понял где была проблема. Но вот интерес и вопрос остался,- как можно реализовать несколько шаблонов меню для одной темы?
Привет!
А куда вставлять вывод, что написан в стандартном варианте и последний блок кода в продвинутом варианте? Ведь в 8-ке отсутствует модуль PHP Filter.
Спасибо.
Никита, поправь код в статье, а то в нем множество артефактов
'my_custom_menu_template' =?> array(
{{>
{{>
\Drupal::menuTree()-?>load(
Хардкодить имя меню плохая практика( $tree = \Drupal::menuTree()->load('main', $menu_tree_parameters);
А как программно добавить несуществующий пункт меню перед выводом меню? Нужна ссылка на раздел, который зависит от текущего местоположения. Не хочется плодить кучу ссылок в самом меню
Примерно так:
use Drupal\Core\Url;
/**
* Implements hook_preprocess_HOOK().
*/
function MYMODULE_preprocess_menu__main(&$variables) {
$items = &$variables['items'];
$items['custom_menu_entry'] = [
'title' => 'Заголовок ссылки',
'url' => Url::fromUri('https://google.ru/'),
'below' => [],
];
}
А как можно загрузить название меню? Здесь только список
Здравствуй! Статья актуальна сегоднч для Друпал9?
Никита, а когда будет смысл заказывать сайт на 8-ке? Или, возможно, когда хорошие исполнители будут браться за 8-ку?
А если, например, мне нужно, чтобы через месяц исполнитель уже стартовал
проект, а на 8-ке ещё не реально, то сколько сайт сможет прожить на 7-ке? Год? Два? Три? Сайт по функционалу уровня рядового агентства недвижимости.