Obtener el Menú de Navegación de WP desde REST API V2

20 nov 2015, 23:45:22
Vistas: 48.1K
Votos: 24

Estoy intentando obtener el menú de navegación desde una respuesta JSON usando el plugin WP REST API v2.

No existe una extensión de menú de navegación para la API REST v2, solo para V1.

Desde el codex de Tipos de Post de WordPress, aprendí que el menú de navegación es tratado como un tipo de post.

Desde la Documentación de Rest API, así es como obtenemos posts de un tipo:

GET http://demo.wp-api.org/wp-json/wp/v2/types/<type>

Intenté obtenerlo de esta manera:

URL : http://localhost/wptest/wp-json/wp/v2/types/nav_menu_item

Recibí un error 403.

{"code":"rest_cannot_read_type","message":"Cannot view type.","data":{"status":403}}

el servidor entendió mi petición pero se negó a entregar los datos.

P: ¿Cómo puedo solucionar esto?

1
Comentarios

Todas estas respuestas son simplemente terribles. Instala esto, extiende aquello. Ya debería estar integrado de fábrica, la comunidad debería abrir un issue en GitHub.

SacWebDeveloper SacWebDeveloper
20 dic 2018 03:16:53
Todas las respuestas a la pregunta 8
5
74

Como a mí tampoco me gusta cuando la mejor respuesta es "Instala el plugin X", aquí te muestro cómo lo resolví:

Actualmente los menús no están disponibles en la API REST de WordPress. Lo que necesitas hacer es registrar tu propio endpoint personalizado y luego simplemente llamar a esa ruta desde tu aplicación que lo necesite.

Entonces incluirías algo como esto (en tu functions.php, plugin, o donde sea):

function get_menu() {
    # Cambia 'menu' por el slug de tu propia navegación.
    return wp_get_nav_menu_items('menu');
}

add_action( 'rest_api_init', function () {
        register_rest_route( 'myroutes', '/menu', array(
        'methods' => 'GET',
        'callback' => 'get_menu',
    ) );
} );

Para el ejemplo anterior, accederías a los datos desde:

http://your-domain.dev/wp-json/myroutes/menu

Puedes usar el método anterior para crear cualquier ruta que desees y obtener cualquier tipo de dato que no esté disponible en la API REST de WordPress. También es útil si necesitas procesar algunos datos antes de enviarlos a tu aplicación.

25 jul 2017 00:20:56
Comentarios

gracias por compartir tu solución alternativa, con más que solo un enlace al plugin ;-) Sería mejor sin embargo prefijar los nombres de tus funciones o usar un espacio de nombres, para evitar posibles colisiones de nombres, ya que get_menu() es bastante genérico.

birgire birgire
25 jul 2017 00:30:58

Increíble, la gente no se da cuenta de que la mayoría ya tiene entre 30 y 70 plugins instalados. ¡Incluso tienen plugins para mantener otros desactivados! Es una locura. Creo que voy a instalar un plugin para mantener este hilo.

Ignacio Bustos Ignacio Bustos
10 jul 2018 01:49:51

solo devuelve false

moeses moeses
16 nov 2018 22:57:10

@moeses solo asegúrate de que el nombre del menú en la configuración de menú en wp-admin sea el mismo nombre que estás pasando como parámetro en la función wp_get_nav_menu_items

Ângelo Rigo Ângelo Rigo
26 ago 2021 16:43:34

@Liren, ¿hay alguna manera de proteger esta ruta? ¿para que solo pueda ser llamada desde archivos de mi aplicación WordPress? ¿protegiéndola de cualquiera que pueda descubrir la ruta?

Ângelo Rigo Ângelo Rigo
26 ago 2021 16:45:34
1

La respuesta de @Liren funciona bien. Sin embargo, algunos principiantes pueden tener dificultades para ajustar la ruta. Aquí está el código que funciona bien con WordPress Rest API v2 con modificaciones mínimas.

Reemplaza solo el nombre de tu menú en la función wp_get_nav_menu_items(). Si el nombre y slug del menú no funcionan (retorna falso), usa el ID del Menú (visible en el Panel de Control al editar ese Menú).

function get_my_menu() {
    // Reemplaza cuidadosamente el nombre, slug o ID de tu menú
    return wp_get_nav_menu_items('Navegación Principal');
}

add_action( 'rest_api_init', function () {
    register_rest_route( 'wp/v2', 'menu', array(
        'methods' => 'GET',
        'callback' => 'get_my_menu',
    ) );
} );

URL de la ruta:

https://website.com/wp-json/wp/v2/menu

Más detalles cubiertos en el Tutorial: WordPress Rest API – Obtener Elementos de Menú de Navegación

23 jun 2019 18:30:52
Comentarios

Es una buena solución para tener solo una ruta

juanitourquiza juanitourquiza
23 ene 2020 18:40:59
1

Existe una extensión de plugin de menú de navegación para la API REST v2: https://wordpress.org/plugins/wp-api-menus/

28 ene 2016 10:27:09
Comentarios

Acabo de visitar el enlace y descubrí que el plugin, desafortunadamente, no ha sido actualizado en 3 años.

David Gaskin David Gaskin
26 mar 2020 02:48:26
0

Opté por la forma más sencilla de hacerlo, manteniéndolo dinámico para que puedas obtener más de un menú.

/**
 * Devuelve los elementos del menú en un array basado en el ID del menú de navegación pasado
 *
 * @param object La solicitud actual donde se pueden acceder a los parámetros.
 * @return array Los elementos del menú contenidos en ese menú específico
 */
function expose_navigation($request) {
  $id = $request['id'];
  return wp_get_nav_menu_items($id);
}

/**
 * Expone bajo /navigation/{id} los elementos del menú en la API wp-json
 *
 * @return void
 */
function expose_navigation_to_rest() {
  register_rest_route( 'wp/v2', '/navigation/(?P<id>\d+)', [
      'methods' => 'GET',
      'callback' => 'expose_navigation'
    ]
  );
}

add_action('rest_api_init', 'expose_navigation_to_rest');

De esta forma es fácilmente consultable como /navigation/{id}

15 jun 2020 16:51:52
2

Debes agregar 'show_in_rest' => true, al registrar el tipo de contenido personalizado.

Consulta los detalles aquí http://v2.wp-api.org/extending/custom-content-types/

21 ene 2016 00:00:30
Comentarios

register_post_type('nav_menu_item', array('show_in_rest' => true));

luukvhoudt luukvhoudt
28 nov 2019 03:24:46

Esta sería una gran solución, pero por una razón que no me resulta obvia, los datos en la respuesta no contienen la información del menú, no hay title, ni description o algo útil (para mí) en la respuesta. ¿Estoy pasando algo por alto?

Johannes Johannes
15 nov 2020 02:37:48
0

Estoy de acuerdo con la respuesta de @Lirens, pero los menús deben llamarse por ID, no por slug. Además, no se necesita la barra inclinada antes de la ruta del menú. Entonces queda algo más como esto:

function get_menu() {
    # Cambia '2' por tu propio ID de navegación.
    return wp_get_nav_menu_items(2);
}

add_action( 'rest_api_init', function () {
    register_rest_route( 'myroutes', 'menu', array(
        'methods' => 'GET',
        'callback' => 'get_menu',
    ) );
} );

Así funcionó para mí.

6 may 2019 18:32:51
0

No creo que se deba usar un plugin para este tipo de tareas. Además, la respuesta de hkc en realidad no es tan mala, solo necesita una explicación más detallada para que funcione con el tipo de post nav_menu_item (el que se usa para los menús de navegación de WordPress).

Este tipo de post ya está registrado, por lo que necesitamos modificarlo. Esto se puede hacer fácilmente enganchando al filtro register_post_type_args. Este filtro nos permite cambiar los argumentos para un tipo de post específico. El código siguiente muestra cómo hacerlo para el tipo de post nav_menu_item.

add_filter('register_post_type_args', function ($args, $post_type) {
    if ($post_type == 'nav_menu_item' &&
        class_exists('WP_REST_Posts_Controller') &&
        !class_exists('WP_REST_NavMenuItem_Controller')) {

        class WP_REST_NavMenuItem_Controller extends WP_REST_Posts_Controller {
            public function get_items( $request ) {
                $args = wp_parse_args($request, [
                    'order' => 'ASC',
                    'orderby' => 'menu_order',
                ]);

                $output = [];

                if (empty($request['menu'])) {
                    $menus = get_registered_nav_menus();

                    foreach ( $menus as $location => $description ) {
                        $items = wp_get_nav_menu_items($location, $args);
                        $output = array_merge($output, is_array($items) ? $items : []);
                    }
                } else {
                    $items = wp_get_nav_menu_items($request['menu'], $args);
                    $output = array_merge($output, is_array($items) ? $items : []);
                }

                return rest_ensure_response($output);
            }

            public function get_collection_params() {
                $query_params = parent::get_collection_params();
                $query_params['menu'] = [
                    'description' => __( 'El nombre o también conocido como theme_location del menú' ),
                    'type' => 'string',
                ];
                return $query_params;
            }
        }

        // Modificamos los argumentos del tipo de post
        $args['show_in_rest'] = true;
        $args['rest_controller_class'] = 'WP_REST_NavMenuItem_Controller';
    }
    return $args;
}, 10, 2);

Como habrás notado en el código anterior, este hace un poco más que simplemente mostrar el tipo de post en REST. También modifica el controlador REST predeterminado de los posts para mostrar una salida similar en REST a la descrita en la respuesta de Liren. Además de eso, hace lo que hacen todos los controladores REST de tipos de post, lo que te da más control y funcionalidad. Considera también que esta es una opción más estable, ya que no entraría en conflicto con otras rutas REST y, por último pero no menos importante, es mucho más conveniente de usar.

23 nov 2018 12:09:29
0

Puedes obtener todos los menús y los datos que están registrados.

Código actualizado:

function get_menu() {
    # Cambia 'menu' por el slug de tu propia navegación.
    $menus = wp_get_nav_menus();
    $menuArray = [];
    foreach($menus as $key=>$menu_term){
        $menuArray[] = nav_sort_menu_items(wp_get_nav_menu_items($menu_term->term_id));
    }
    return $menuArray;
}

add_action( 'rest_api_init', function () {
        register_rest_route( 'route', '/menu', array(
        'methods' => 'GET',
        'callback' => 'get_menu',
    ) );
} );

Luego puedes obtener los datos desde

27 oct 2023 14:49:21