Получить меню навигации WP из REST API V2

14

Я пытаюсь получить навигационное меню из ответа JSON с помощью плагина WP REST API v2 .

Для REST API v2 отсутствует расширение плагина навигационного меню , но только для V1.

Из кодекса WordPress Post Types я узнал, что навигационное меню рассматривается как тип записи.

Из Rest API Doc вот как мы получаем сообщения типа:

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

Я пытался получить это так:

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

Я получил ошибку 403.

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

сервер понял мой запрос, но отказался предоставить данные.

Q: Как я могу это исправить?

Мурхаф Сусли
источник
Все эти ответы просто ужасны. Установите это, расширьте это. Он должен быть уже встроенным, сообщество должно открыть вопрос на GitHub.
SacWebDeveloper

Ответы:

47

Поскольку мне самому не нравится, когда главный ответ - «Установить плагин X», я решил это так:

В настоящее время меню в WP Rest недоступны. Итак, вам нужно зарегистрировать свою собственную конечную точку, а затем просто вызвать этот маршрут из приложения, которому это нужно.

Таким образом, вы бы включили что-то вроде этого (в вашем functions.php, плагин, где угодно):

function get_menu() {
    # Change 'menu' to your own navigation slug.
    return wp_get_nav_menu_items('menu');
}

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

В приведенном выше примере вы получите доступ к данным из:

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

Вы можете использовать вышеуказанный метод для создания любых маршрутов, которые вам нравятся, чтобы получить любой тип данных, который недоступен в WP Rest. Также хорошо, если вам нужно обработать некоторые данные перед отправкой в ​​ваше приложение.

Liren
источник
4
спасибо за то, что поделились своим решением, используя не просто ссылку на плагин ;-) Было бы лучше, если бы к вашим именам функций добавлялся префикс или использовалось пространство имен, чтобы избежать возможного конфликта имен, как get_menu()это обычно бывает.
birgire
Удивительно, люди не понимают, что большинство людей уже установили от 30 до 70 плагинов. У них даже есть плагины, чтобы отключить других! это безумие Я думаю, что я собираюсь установить плагин, чтобы сохранить эту тему.
Игнасио Бустос
это только выводfalse
moesphemie
1

@Liren ответ работает хорошо. Однако немногие новички не могут настроить маршрут. Вот код, который хорошо работает с WordPress Rest API v2 с минимальными изменениями.

Замените название вашего меню только в функции wp_get_nav_menu_items () . Если имя меню и slug не работают (Return false), используйте идентификатор меню (отображается в Dashboard при редактировании этого меню).

function get_my_menu() {
    // Replace your menu name, slug or ID carefully
    return wp_get_nav_menu_items('Main Navigation');
}

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

URL маршрута:

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

Более подробная информация описана в руководстве: WordPress Rest API - Получить элементы навигационного меню.

Дипак Раджпал
источник
Это хорошее решение для одного маршрута
juanitourquiza
0

Я не думаю, что плагин должен использоваться для такого рода задач. Кроме того, ответ hkc на самом деле не так уж и плох, ему нужно только дополнительное объяснение, чтобы заставить эту работу работать с nav_menu_itemтипом записей (тот, который используется для навигационных меню wp).

Этот тип записи уже зарегистрирован, и поэтому нам нужно изменить его, это легко сделать, подключившись к register_post_type_argsфильтру. Этот фильтр позволяет нам изменять аргументы для определенного типа записи. Код ниже показывает только это для 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' => __( 'The name or also known as theme_location of the menu' ),
                    'type' => 'string',
                ];
                return $query_params;
            }
        }

        // Alter the post type arguments
        $args['show_in_rest'] = true;
        $args['rest_controller_class'] = 'WP_REST_NavMenuItem_Controller';
    }
    return $args;
}, 10, 2);

Как вы могли заметить из приведенного выше кода, код делает немного больше, чем просто показывает тип записи в REST. Он также изменяет контроллер REST Posts по умолчанию, чтобы показать несколько похожий вывод в REST, как описано в ответе Liren . Несмотря на это, он также делает то, что делают все REST-контроллеры пост-типа и, таким образом, дает вам больше контроля и функциональности. Также рассмотрите это как более стабильные варианты, поскольку это не будет конфликтовать с другими маршрутами REST и, что не менее важно, с ним также удобнее работать.

Fleuv
источник
0

Я согласен с ответом @Lirens, но меню должно вызываться по идентификатору, а не по слагу. Также косая черта перед путем меню не нужна. Так что это становится чем-то вроде этого:

function get_menu() {
    # Change '2' to your own navigation ID.
    return wp_get_nav_menu_items(2);
}

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

Вот так это сработало для меня.

Шёрд Удман
источник