Ottieni Menu di Navigazione WP dalla REST API V2
Sto cercando di ottenere il menu di navigazione dalla risposta JSON utilizzando il plugin WP REST API v2.
Non esiste un'estensione del plugin per il menu di navigazione per la REST API v2, ma solo per V1.
Dal codex WordPress Post Types, ho appreso che il menu di navigazione viene trattato come un tipo di post.
Dalla documentazione Rest API, questo è il modo in cui otteniamo i post di un determinato tipo:
GET http://demo.wp-api.org/wp-json/wp/v2/types/<type>
Ho provato ad ottenerlo in questo modo:
URL : http://localhost/wptest/wp-json/wp/v2/types/nav_menu_item
Ho ricevuto un errore 403.
{"code":"rest_cannot_read_type","message":"Impossibile visualizzare il tipo.","data":{"status":403}}
il server ha compreso la mia richiesta ma si è rifiutato di fornire i dati.
D: Come posso risolvere questo problema?

Dato che a me per primo non piace quando la risposta migliore è "Installa il plugin X", ecco come ho risolto:
Attualmente i menu non sono disponibili nell'API REST di WordPress. Quindi quello che devi fare è registrare il tuo endpoint personalizzato e poi chiamare quella route dall'applicazione che ne ha bisogno.
Dovresti includere qualcosa come questo (nel tuo functions.php, in un plugin, o dove preferisci):
function get_menu() {
# Cambia 'menu' con lo slug della tua navigazione
return wp_get_nav_menu_items('menu');
}
add_action( 'rest_api_init', function () {
register_rest_route( 'myroutes', '/menu', array(
'methods' => 'GET',
'callback' => 'get_menu',
) );
} );
Per l'esempio sopra potresti accedere ai dati da:
http://tuo-dominio.dev/wp-json/myroutes/menu
Puoi usare il metodo sopra per creare qualsiasi route ti serva per ottenere dati non disponibili nell'API REST di WP. Utile anche se hai bisogno di elaborare alcuni dati prima di inviarli alla tua applicazione.

grazie per aver condiviso la tua soluzione alternativa, con qualcosa in più del semplice link a un plugin ;-) Sarebbe meglio però prefissare i nomi delle tue funzioni o usare i namespace, per evitare possibili collisioni di nomi, dato che get_menu()
è piuttosto generico.

Fantastico, la gente non si rende conto che la maggior parte delle persone ha già dai 30 ai 70 plugin installati. Hanno persino plugin per tenere disattivati gli altri! È pazzesco. Penso che installerò un plugin per mantenere questo thread.

@moeses assicurati solo che il nome del menu nelle impostazioni del menu in wp-admin sia lo stesso nome che stai passando come parametro nella funzione wp_get_nav_menu_items

La risposta di @Liren funziona bene. Tuttavia, alcuni principianti potrebbero non riuscire a modificare la route. Ecco il codice che funziona bene con WordPress Rest API v2 con modifiche minime.
Sostituisci solo il nome del tuo menu nella funzione wp_get_nav_menu_items(). Se il nome o lo slug del menu non funzionano (restituiscono false), utilizza l'ID del Menu (visibile nel Pannello di controllo durante la modifica del Menu).
function get_my_menu() {
// Sostituisci con attenzione il nome, lo slug o l'ID del tuo menu
return wp_get_nav_menu_items('Menu Principale');
}
add_action( 'rest_api_init', function () {
register_rest_route( 'wp/v2', 'menu', array(
'methods' => 'GET',
'callback' => 'get_my_menu',
) );
} );
URL della route:
https://website.com/wp-json/wp/v2/menu
Maggiori dettagli sono trattati nel Tutorial: WordPress Rest API – Ottenere gli Elementi del Menu di Navigazione

Esiste un'estensione del plugin per il menu di navigazione per l'API REST v2: https://wordpress.org/plugins/wp-api-menus/

Ho optato per il modo più semplice per farlo, mantenendolo comunque dinamico così da poter recuperare più di un menu.
/**
* Restituisce gli elementi del menu in un array basato sull'ID del menu di navigazione passato
*
* @param object La richiesta attuale da cui è possibile accedere ai parametri.
* @return array Gli elementi del menu contenuti in quel menu specifico
*/
function expose_navigation($request) {
$id = $request['id'];
return wp_get_nav_menu_items($id);
}
/**
* Espone sotto /navigation/{id} gli elementi del menu nell'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');
In modo che sia facilmente interrogabile come /navigation/{id}

Devi aggiungere 'show_in_rest' => true,
durante la registrazione del tipo di post.
Vedi dettagli qui http://v2.wp-api.org/extending/custom-content-types/

Sono d'accordo con la risposta di @Lirens, ma i menu dovrebbero essere chiamati per ID, non per slug. Inoltre, la barra prima del percorso del menu non è necessaria. Quindi diventa qualcosa di più simile a questo:
function get_menu() {
# Cambia '2' con il tuo ID di navigazione.
return wp_get_nav_menu_items(2);
}
add_action( 'rest_api_init', function () {
register_rest_route( 'myroutes', 'menu', array(
'methods' => 'GET',
'callback' => 'get_menu',
) );
} );
In questo modo ha funzionato per me.

Non credo che un plugin debba essere utilizzato per questo tipo di attività. Inoltre la risposta di hkc in realtà non è così male, ha solo bisogno di qualche spiegazione aggiuntiva per farla funzionare con il tipo di post nav_menu_item
(quello utilizzato per i menu di navigazione di WordPress).
Questo tipo di post è già registrato e quindi dobbiamo modificarlo, cosa che può essere facilmente fatta agganciandosi al filtro register_post_type_args
. Questo filtro ci permette di cambiare gli argomenti per un specifico tipo di post. Il codice qui sotto mostra proprio questo per il tipo di 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' => __( 'Il nome o anche conosciuto come theme_location del menu' ),
'type' => 'string',
];
return $query_params;
}
}
// Modifica gli argomenti del tipo di post
$args['show_in_rest'] = true;
$args['rest_controller_class'] = 'WP_REST_NavMenuItem_Controller';
}
return $args;
}, 10, 2);
Come potresti aver notato dal codice sopra, il codice fa qualcosa in più rispetto al semplice mostrare il tipo di post nella REST. Modifica anche il controller REST predefinito dei post per mostrare un output nella REST simile a quello descritto nella risposta di Liren. Oltre a questo però fa anche tutto ciò che fanno i controller REST dei tipi di post e quindi ti dà più controllo e funzionalità. Considera anche che questa è un'opzione più stabile in quanto non entrerebbe in conflitto con altre route REST e, non meno importante, è anche molto più comoda da utilizzare.

Puoi ottenere tutti i menu e i dati che sono registrati.
Codice aggiornato:
function get_menu() {
# Cambia 'menu' con il tuo slug di navigazione personalizzato.
$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',
) );
} );
Puoi quindi ottenere i dati da
