Посібник WordPress: спеціальне меню для публікацій або сторінок на бічній панелі
Ця публікація призначена для тих, хто керує сайтом WordPress із великою кількістю вмісту, можливо, багатьма сторінками, структурованими в ієрархії, і бажає кращої навігації за межами головного меню. Щоб полегшити навігацію сайтом, надзвичайно допоможе спеціальне меню, пов’язане з поточною публікацією. Проблема з розміщенням віджета меню на бічній панелі (або де завгодно) полягає в тому, що бічна панель є звичайною. У цій публікації ми дізнаємося, як показувати додаткове спеціальне меню на бічній панелі, дозволяючи публікаціям, сторінкам або спеціальним типам публікацій вибирати меню.
Додайте наведений нижче код у свою тему functions.phpабо в код плагіна.
Створювати меню в WordPress легко, і ви можете використовувати віджет «Меню», щоб відобразити меню на бічній панелі. Проблема в тому, що бічна панель є глобальною, і те саме меню буде відображатися всюди. Що робити, якщо ви бажаєте, щоб певні меню відображалися на певних сторінках? Ви також дізнаєтеся, як переконатися, що вибране меню успадковується дочірніми сторінками. Таким чином вам потрібно лише вибрати меню на головній сторінці. Будь-які підсторінки також відображатимуть те саме меню без необхідності редагувати їх усі.
Першим кроком є створення метабокса в публікаціях або на сторінках, де ми отримуємо можливість вибрати меню. Ми використовуємо функцію add_meta_box()та вирішуємо, для яких типів публікацій ми хочемо її показувати.
add_action('add_meta_boxes', function() {
add_meta_box('metabox-sidebar-menu', __('Sidebar Menu', 'txtdomain'), 'awp_sidebar_menu_metabox_callback', ['post', 'page']);
});
Налаштуйте наведений вище код відповідно до потрібного типу заголовка та публікації. Наведений вище приклад додасть метабокс як до публікацій, так і до сторінок. Третій параметр, який я назвав awp_sidebar_menu_metabox_callback, — це функція, відповідальна за рендеринг вмісту метабокса. Давайте визначимо це далі. Ось що нам потрібно буде зробити в нашому метабоксі:
function awp_sidebar_menu_metabox_callback($post) {
// Get all menus
// Get the current saved menu, if set
// Output HTML with a select showing all menus, and mark the currently saved one as selected
}
Ми можемо отримати масив із усіма збереженими меню в WordPress за допомогою wp_get_nav_menus(). Що стосується отримання поточного вибраного меню, ми зберігаємо вибране меню як мета допису awp_sidebar_menu(назвіть його як завгодно), і ми просто отримаємо значення на основі поточного $post, наданого нам у функції metabox. Ми збережемо ідентифікатори меню, оскільки це все, що нам потрібно для відображення меню. Потім ми виводимо HTML для вибору, який проходить по меню. HTML-вихід метабокса насправді залежить від вас, нижче наведено приклад. Я також включив функцію nonce для безпеки.
function awp_sidebar_menu_metabox_callback($post) {
// Get all menus
$menus = wp_get_nav_menus();
// Get the current saved menu, if set
$current_selected = get_post_meta($post->ID, 'awp_sidebar_menu', true);
// Output HTML with a select showing all menus, and mark the currently saved one as selected
wp_nonce_field('awp_sidebar_menu_metabox_nonce', 'awp_sidebar_menu_nonce');
?><div class="awp-metabox-item">
<div class="awp-metabox-label"><label><?php _e('Choose menu', 'txtdomain'); ?></label></div>
<div class="awp-metabox-input"><?php
if (empty($menus)) {
echo '<p>'. __('No menus created.', 'txtdomain'). '</p>';
} else { ?>
<select name="awp-sidebar-menu" id="awp-sidebar-menu">
<?php
echo '<option value="">'. __('Choose menu', 'txtdomain'). '</option>';
foreach ($menus as $menu) {
echo '<option value="'. $menu->term_id. '" '.selected($current_selected, $menu->term_id).'>'.$menu->name.'</option>';
} ?>
</select>
<?php } ?>
</div>
</div><?php
}
У вихідних даних HTML я друкую мітку. Якщо в WordPress взагалі немає збережених меню, він просто відобразить абзац. В іншому випадку буде створено вибір із ідентифікаторами меню як значеннями та назвами меню як міткою. Я також додаю порожній вибір, щоб дозволити повідомленням не показувати меню. Я використовую допоміжну функцію WordPress, [selected](https://developer.wordpress.org/reference/functions/selected/)()щоб позначити поточний збережений параметр як вибраний.
Якщо ви редагуєте публікацію чи сторінку, унизу має з’явитися метабокс із вказівкою на ваш вибір. Чудово! Однак наразі він не збереже ваш вибір меню, коли ви збережете публікацію. Це наступний крок.
Ми використовуємо хук save_post, щоб створити функцію, яка зберігає будь-який вибір, який ми додали в наш метабокс. Хук save_postспрацьовує кожного разу, коли публікація зберігається або оновлюється. Спочатку ми перевіримо nonce (якщо ви не впевнені, що таке nonce, перегляньте цей посібник WordPress про nonce ). Потім ми ще раз перевіряємо, чи дозволено користувачеві оновлювати дописи, і оновлюємо мета нашого допису за вибором.
add_action('save_post', function($post_id) {
if (!isset($_POST['awp_sidebar_menu_nonce']) || !wp_verify_nonce($_POST['awp_sidebar_menu_nonce'], 'awp_sidebar_menu_metabox_nonce')) {
return;
}
if (!current_user_can('edit_post', $post_id)) {
return;
}
update_post_meta($post_id, 'awp_sidebar_menu', $_POST['awp-sidebar-menu']);
});
Тепер, коли ви оновлюєте дописи, це також збереже ваш вибір меню.
І це все, що стосується вибору публікації. Наступним кроком є фактичне виведення меню, якщо меню було вибрано.
Я додаю результат на бічній панелі, але ви можете вивести його будь-де в шаблонах вашої теми. Нам просто потрібен або попередньо визначений хук, або визначте свій власний. Як приклад, я додаю спеціальний хук у верхній частині бічної панелі, щоб я міг створити функцію, підключену до цього.
Ви можете просто викликати wp_nav_menu()безпосередньо в шаблоні, але я рекомендую замість цього створити спеціальний хук, оскільки ми додамо досить багато коду, і це може здатися безладним.
У моїй темі, яку я редагую sidebar.php, я безпосередньо перед dynamic_sidebar()викликом бічної панелі (куди додаються віджети) додаю власний хук із do_action()іменем. Ви можете називати це як завгодно, але воно має бути унікальним у WordPress. Тож принаймні додайте до нього щось унікальне для вас.
<aside class="sidebar">
<?php
do_action('awp_before_sidebar');
dynamic_sidebar('left-sidebar');
?>
</aside>
Тепер ми можемо повернутися до functions.php, визначити функцію, підключену до awp_before_sidebarі її результат буде відображатися на бічній панелі перед віджетами. Функція використовуватиме умовні теги WordPress, щоб перевірити, чи ми зараз показуємо одну публікацію чи сторінку. І якщо так, я отримаю мета нашої публікації. Якщо було встановлено мета публікації, ми виводимо меню, викликаючи [wp_nav_menu](https://developer.wordpress.org/reference/functions/wp_nav_menu/)()та надаючи ідентифікатор збереженого меню як його menuпараметр.
add_action('awp_before_sidebar', function() {
if (is_singular()) {
global $post;
$sidebar_menu = get_post_meta($post->ID, 'awp_sidebar_menu', true);
}
if (!empty($sidebar_menu)) {
?><section class="widget awp-sidebar-menu">
<?php wp_nav_menu(['menu' => $sidebar_menu]); ?>
</section><?php
}
});
Ви повинні налаштувати HTML навколо меню, щоб воно відповідало решті вмісту. У наведеному вище коді я загортаю меню в той самий HTML, у який загорнуті всі віджети на бічній панелі, щоб стиль віджета теми застосовувався до нашого спеціального меню.
Це воно! Щоразу, коли ви вибираєте меню в дописі або на сторінці, меню буде виводитися над бічною панеллю під час перегляду цього допису або сторінки.
Але ми можемо зробити ще один крок далі. Якщо ви хочете, щоб дочірні сторінки відображали те саме меню бічної панелі в будь-якому з батьківських сторінок, читайте далі.
Ця додаткова функція має сенс, якщо у вас є багато сторінок в ієрархії або користувацький тип публікації з увімкненою ієрархією. Було б надто громіздко редагувати кожну дочірню сторінку та вибирати одне й те саме меню. У такому випадку було б краще вибрати меню на батьківській сторінці та автоматично дозволити всім підсторінкам «успадкувати» цей вибір меню. Якщо будь-яка підсторінка вибере інше меню, це меню буде показано замість «успадкованого» один раз.
У нашу функцію, підключену до awp_before_sidebar, ми додамо фрагмент коду всередину перевірки, чи переглядаємо ми окрему публікацію чи сторінку:
...
$sidebar_menu = get_post_meta($post->ID, 'awp_sidebar_menu', true);
if (!empty($sidebar_menu)) {
$parents = get_post_ancestors($post->ID);
if (!empty($parents)) {
// go step by step up the parents tree
for ($i = 0; $i < count($parents); $i++) {
$sidebar_menu = get_post_meta($post->ID, 'awp_sidebar_menu', true);
if (!empty($sidebar_menu)) {
break;
}
}
}
}
}
if (!empty($sidebar_menu)) {
...
Те, що наведений вище код робить, якщо меню не знайдено на поточній сторінці, отримує всі батьківські елементи з [get_post_ancestors](https://developer.wordpress.org/reference/functions/get_post_ancestors/)(). Ця функція повертає масив ідентифікаторів батьківських публікацій, упорядкованих спочатку за найближчим батьківським. Якщо сторінка не має батьків (наприклад, якщо це публікація), повертається порожній масив. І якщо є будь-які батьки, ми переглядаємо кожного з батьків по черзі та перевіряємо, чи вони встановили нашу мета публікації. Якщо такий знайдено, ми виходимо з обходу батьків і $sidebar_menuбуде встановлено, а меню буде виведено пізніше за допомогою wp_nav_menu().
І це все для функції «успадкування»!