Как подсчитать количество пунктов в меню навигации?

3 дек. 2011 г., 00:57:31
Просмотры: 15.9K
Голосов: 9

Я создаю кастомный Walker для своего меню навигации. Цель — разделить меню на колонки, как показано ниже:

Пример меню с колонками

Я могу легко определить текущую позицию в списке, используя $item->menu_order. Но я не знаю, как получить общее количество пунктов в меню.

Как я могу это узнать изнутри Walker?

Обновление:

Я понимаю, что есть несколько других способов создания колонок, но у всех есть недостатки:

  1. CSS Floats. Как предложил @sagive, можно разместить элементы списка с помощью float. Проблема в том, что порядок элементов меняется. Вместо заполнения первой колонки сверху вниз, элементы идут по строкам через все колонки, что нарушает логический порядок.

  2. CSS Columns. Это почти идеальное решение, дающее нужный результат. Но оно не работает в IE, даже в 9 версии, что делает его непригодным для mainstream сайтов.

  3. jQuery. Клиентский JavaScript мог бы перестроить список, но это грязное решение, которое не работает при отключенном JS.

  4. PHP. Именно этот метод я рассматриваю в данном вопросе. Разделение списка на 4 отдельных <ul>, вывод каждого через CSS float даёт кроссбраузерный результат, что делает этот вариант предпочтительным.

Решение:

Для тех, кто столкнётся с подобной задачей, вот рабочий код:

// Хэндл меню из register_nav_menu в functions.php
$theme_location = 'my-menu-handle';

$theme_locations = get_nav_menu_locations();

$menu_obj = get_term( $theme_locations[$theme_location], 'nav_menu' );

// Выводим количество пунктов в меню
echo $menu_obj->count;
0
Все ответы на вопрос 4
3
12

Вызовите wp_get_nav_menu_object, чтобы получить объект меню. Количество элементов будет одним из свойств объекта, обратитесь к нему следующим образом:

Пример:

// Получаем объект меню
$my_menu = wp_get_nav_menu_object( 'your-menu-name-or-slug' );

// Выводим количество элементов в меню
echo $my_menu->count;

Также для ответа на дополнительный вопрос в комментариях о получении всех элементов верхнего уровня меню. Учитывая, что меню являются типом записи с мета-ключами, можно вызвать wp_get_nav_menu_items с аргументами meta_key и meta_value, чтобы получить только элементы верхнего уровня меню, например так.

Пример:

$args = array( 'meta_key' => '_menu_item_menu_item_parent', 'meta_value' => 0 );

$top_items = wp_get_nav_menu_items( 'mymenuname', $args );

Надеюсь, это поможет.

3 дек. 2011 г. 16:34:04
Комментарии

Спасибо! Это не дало мне именно то, что я хотел, но было достаточно близко, чтобы помочь найти ответ. Проблема была в том, что я не знаю название меню или его slug, только название темы, указанное в register_nav_menu. Однако я нашел код для определения названия меню. Имея это на руках, я смог использовать ваш код выше.

Axeva Axeva
3 дек. 2011 г. 17:40:11

Ах... вы не указали это в своем вопросе, если бы вы это сделали, я бы, вероятно, добавил еще немного кода для определения названия меню. В любом случае, рад был помочь.. ;)

t31os t31os
3 дек. 2011 г. 18:24:56

Можно ли как-то отфильтровать это, чтобы считать только элементы меню верхнего уровня и игнорировать подменю и их элементы?

Usce Usce
12 нояб. 2018 г. 02:07:11
0

Почему бы просто не использовать функцию array_chunk()?

Предположим, вы создали массив готовых тегов <li>, ваш код для разделения и отображения может выглядеть так:

$columns = array_chunk( $myArray, 4 );
foreach ( $columns as $column ) {
    echo '<li>' . $column . '</ul>';
}
23 янв. 2015 г. 21:17:05
1

Вам не кажется (и извините, если это грубо), что гораздо проще и легче
просто задать float:left; для всех "li" и поместить их внутрь div с
фоном-изображением этой структуры??

Пример:

<style type="text/css">
.fourPartMenu {
    border: 1px solid #444;
    width: 800px;
    padding: 10px 15px;
}

.fourPartMenu ul {
    list-style: circle; // замените на ваше изображение
    padding: 0px;
    margin: 0px;
}

.fourPartMenu ul li {
    float: left;
    width: 190px;
}

</style>

<div class="fourPartMenu">
    <ul>
        <li><a href="#">Один</a></li>
        <li><a href="#">Два</a></li>
        <li><a href="#">Три</a></li>
        <li><a href="#">Четыре</a></li>
        <li><a href="#">Пять</a></li>
        <li><a href="#">Шесть</a></li>
        <li><a href="#">Семь</a></li>
        <li><a href="#">Восемь</a></li>
        <li><a href="#">Девять</a></li>
        <li><a href="#">Десять</a></li>
    </ul>
</div>

Мне кажется, это было бы гораздо проще реализовать - но.. я понимаю, что это не совсем то, что вам нужно, хотя свежий взгляд иногда помогает :)

3 дек. 2011 г. 01:25:12
Комментарии

Спасибо за ответ. Я понимаю, что можно сделать это с помощью CSS, но список будет не в том порядке. Если идти по колонкам сверху, то получится один, два, три, четыре в верхней части. Мне же нужно: один, четыре, семь, девять. Другими словами, список должен идти вниз по первой колонке, затем вниз по второй колонке и так далее.

Axeva Axeva
3 дек. 2011 г. 16:16:53
0

Я знаю, что вы уже нашли решение и не уверен, что это именно то, что вы ищете, но некоторое время назад я написал плагин для использования на сайте клиента, который создает классы для каждого меню, подменю и пункта меню. Он называется Advanced Navigation Menus. Если вы решите его использовать, не стесняйтесь присылать мне запросы на новые функции.

3 дек. 2011 г. 18:31:50