Cómo contar elementos en un menú de navegación

3 dic 2011, 00:57:31
Vistas: 15.9K
Votos: 9

Estoy creando un walker personalizado para mi menú de navegación. El objetivo es dividir el menú en columnas como se muestra:

Ejemplo de menú dividido en columnas

Puedo determinar fácilmente mi posición en la lista mirando $item->menu_order. Lo que no sé es cuántos elementos hay en total en el menú.

¿Cómo puedo obtener esa información desde dentro del walker?

Actualización:

Reconozco que hay varias formas de crear columnas. Todas tienen sus desventajas:

  1. CSS Floats. Como sugiere @sagive, esto podría lograrse flotando todos los elementos de la lista. El problema es que cambia el orden. En lugar de bajar por la primera columna y luego pasar a la segunda, la lista iría a través de las cuatro columnas en la primera fila, luego en la segunda fila. Esto desordena la secuencia.

  2. Columnas CSS. Esta es casi la solución perfecta. Me daría exactamente lo que quiero, excepto que IE no lo soporta. Ni siquiera en IE 9. Esto lo hace inutilizable para un sitio web mainstream.

  3. jQuery. Con algo de JavaScript del lado del cliente podría modificar la lista para que se muestre como quiero. Pero es desordenado y no funciona para quienes tienen JS deshabilitado.

  4. PHP. Este es el método sobre el que pregunto en esta cuestión. Divido la lista en cuatro listas desordenadas separadas, las muestro en HTML y uso CSS para flotar las listas y crear cuatro columnas distintas. Puede ser complicado de producir en PHP, pero el resultado se ve igual en todos los navegadores. Por eso creo que es la mejor opción.

Solución:

Para quienes puedan seguir este hilo, aquí está el código que finalmente usé para obtener la respuesta:

// El handle del menú del register_nav_menu en functions.php
$theme_location = 'my-menu-handle';

$theme_locations = get_nav_menu_locations();

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

// Mostrar el conteo de elementos en el menú
echo $menu_obj->count;
0
Todas las respuestas a la pregunta 4
3
12

Llama a wp_get_nav_menu_object para obtener un objeto de menú. El conteo será una de las propiedades del objeto, se referencia así:

Ejemplo:

// Obtener el objeto del menú
$my_menu = wp_get_nav_menu_object( 'tu-nombre-de-menú-o-slug' );

// Mostrar el conteo de elementos en el menú
echo $my_menu->count;

Además, para responder más a fondo la pregunta adicional en los comentarios sobre cómo obtener todos los elementos de menú de nivel superior. Dado que los menús son un tipo de publicación con metaclaves, es posible llamar a wp_get_nav_menu_items con los argumentos meta_key y meta_value y obtener solo los menús de nivel superior, así:

Ejemplo:

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

$top_items = wp_get_nav_menu_items( 'mimenú', $args );

Espero que eso ayude.

3 dic 2011 16:34:04
Comentarios

¡Gracias! Eso no me dio exactamente lo que quería, pero estuvo lo suficientemente cerca como para ayudarme a encontrar la respuesta. El problema era que no conocía el nombre del menú ni el slug, solo el nombre del tema establecido en la declaración register_nav_menu. Sin embargo, encontré algo de código para determinar el nombre del menú. Con eso en mano, pude usar tu código anterior.

Axeva Axeva
3 dic 2011 17:40:11

Ah... no mencionaste eso en tu pregunta, si lo hubieras hecho probablemente habría incluido más código para averiguar el nombre del menú también. De cualquier forma, me alegra haber ayudado.. ;)

t31os t31os
3 dic 2011 18:24:56

¿Es posible filtrar esto de alguna manera para contar solo los elementos del menú de nivel superior e ignorar los submenús y los elementos de submenú?

Usce Usce
12 nov 2018 02:07:11
0

¿Por qué no usar simplemente la función array_chunk()?

Asumiendo que has construido un array de etiquetas <li> terminadas, tu código para dividirlas y mostrarlas podría verse así:

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

¿No crees (y disculpa si soy grosero) que sería mucho más simple y fácil
simplemente aplicar float:left; a todos los "li" y colocarlos dentro de un div con ese
fondo de estructura como una imagen??

Ejemplo:

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

.fourPartMenu ul {
    list-style: circle; // reemplaza con tu img
    padding: 0px;
    margin: 0px;
}

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

</style>

<div class="fourPartMenu">
    <ul>
        <li><a href="#">Uno</a></li>
        <li><a href="#">Dos</a></li>
        <li><a href="#">Tres</a></li>
        <li><a href="#">Cuatro</a></li>
        <li><a href="#">Cinco</a></li>
        <li><a href="#">Seis</a></li>
        <li><a href="#">Siete</a></li>
        <li><a href="#">Ocho</a></li>
        <li><a href="#">Nueve</a></li>
        <li><a href="#">Diez</a></li>
    </ul>
</div>

Creo que sería mucho más fácil de implementar, pero... sé que no es exactamente lo que buscas, aunque a veces una nueva perspectiva ayuda :)

3 dic 2011 01:25:12
Comentarios

Gracias por la respuesta. Entiendo que podría hacerlo con CSS, pero la lista quedaría desordenada. Al recorrer las columnas obtendrías uno, dos, tres, cuatro en la parte superior. Lo que necesito es uno, cuatro, siete, nueve. En otras palabras, la lista baja por la primera columna, luego por la segunda columna, y así sucesivamente.

Axeva Axeva
3 dic 2011 16:16:53
0

Ya sé que probablemente ya encontraste una solución y no sé si es exactamente lo que estás buscando, pero hace un tiempo escribí un plugin para usar en el sitio de un cliente que crea clases para cada menú, submenú y elemento del menú. Se llama Advanced Navigation Menus. Si terminas usándolo, no dudes en enviarme solicitudes de características.

3 dic 2011 18:31:50