Получение меню навигации WordPress через REST API V2

20 нояб. 2015 г., 23:45:22
Просмотры: 48.1K
Голосов: 24

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

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

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

Из документации Rest API, вот как мы получаем записи определенного типа:

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}}

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

Вопрос: Как это исправить?

1
Комментарии

Все эти ответы просто ужасны. Установи это, расширь то. Это должно быть встроено изначально, сообществу стоит создать issue на GitHub.

SacWebDeveloper SacWebDeveloper
20 дек. 2018 г. 03:16:53
Все ответы на вопрос 8
5
74

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

Меню в настоящее время недоступны в WP REST API. Поэтому вам нужно зарегистрировать собственный пользовательский endpoint, а затем просто вызывать этот маршрут из вашего приложения, которому это необходимо.

Вы можете добавить что-то вроде этого (в functions.php, плагин или где угодно):

function get_menu() {
    # Измените 'menu' на ваш собственный слаг навигации.
    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 API. Также это полезно, если вам нужно обработать какие-то данные перед отправкой в ваше приложение.

25 июл. 2017 г. 00:20:56
Комментарии

спасибо, что поделились своим решением, а не просто кинули ссылку на плагин ;-) Однако лучше было бы добавить префикс к названиям ваших функций или использовать пространство имен, чтобы избежать возможных конфликтов, так как get_menu() - довольно общее название.

birgire birgire
25 июл. 2017 г. 00:30:58

Потрясающе, люди не понимают, что у большинства уже установлено от 30 до 70 плагинов. У них даже есть плагины для деактивации других плагинов! Это безумие. Думаю, я установлю плагин, чтобы сохранить эту ветку.

Ignacio Bustos Ignacio Bustos
10 июл. 2018 г. 01:49:51

он выводит только false

moeses moeses
16 нояб. 2018 г. 22:57:10

@moeses просто убедитесь, что название меню в настройках меню в wp-admin совпадает с названием, которое вы передаёте в функцию wp_get_nav_menu_items в качестве параметра

Ângelo Rigo Ângelo Rigo
26 авг. 2021 г. 16:43:34

@Liren, есть ли способ защитить этот маршрут? чтобы я мог вызывать его только из файлов моего WordPress приложения? защититься от тех, кто может обнаружить этот маршрут?

Ângelo Rigo Ângelo Rigo
26 авг. 2021 г. 16:45:34
1

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

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

function get_my_menu() {
    // Внимательно замените название меню, его ярлык или ID
    return wp_get_nav_menu_items('Основная навигация');
}

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 – Получение элементов навигационного меню

23 июн. 2019 г. 18:30:52
Комментарии

Это хорошее решение, если у вас только один маршрут

juanitourquiza juanitourquiza
23 янв. 2020 г. 18:40:59
1

Существует расширение плагина для навигационного меню в REST API v2: https://wordpress.org/plugins/wp-api-menus/

28 янв. 2016 г. 10:27:09
Комментарии

Я только что посетил ссылку и обнаружил, что плагин, к сожалению, не обновлялся уже 3 года.

David Gaskin David Gaskin
26 мар. 2020 г. 02:48:26
0

Я выбрал самый простой способ сделать это, сохраняя при этом динамичность, чтобы можно было получить более одного меню.

/**
 * Возвращает элементы меню в виде массива на основе переданного ID навигационного меню
 *
 * @param object Запрос, из которого можно получить параметры.
 * @return array Элементы меню, содержащиеся в указанном меню
 */
function expose_navigation($request) {
  $id = $request['id'];
  return wp_get_nav_menu_items($id);
}

/**
 * Предоставляет доступ к элементам меню через WP REST API по пути /navigation/{id}
 *
 * @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');

Таким образом, меню можно легко запросить по пути /navigation/{id}

15 июн. 2020 г. 16:51:52
2

При регистрации типа записи необходимо добавить параметр 'show_in_rest' => true,.

Подробнее можно узнать по ссылке http://v2.wp-api.org/extending/custom-content-types/

21 янв. 2016 г. 00:00:30
Комментарии

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

luukvhoudt luukvhoudt
28 нояб. 2019 г. 03:24:46

Это было бы отличным решением, но по неочевидной для меня причине данные в ответе не содержат информации о меню - там нет title, нет description или чего-то полезного (для меня) в ответе. Я что-то упускаю?

Johannes Johannes
15 нояб. 2020 г. 02:37:48
0

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

function get_menu() {
    # Замените '2' на 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',
    ) );
} );

В таком виде у меня сработало.

6 мая 2019 г. 18:32:51
0

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

Этот тип записи уже зарегистрирован, поэтому нам нужно его изменить. Это легко сделать, подключившись к фильтру 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' => __( 'Имя или theme_location меню' ),
                    'type' => 'string',
                ];
                return $query_params;
            }
        }

        // Изменяем аргументы типа записи
        $args['show_in_rest'] = true;
        $args['rest_controller_class'] = 'WP_REST_NavMenuItem_Controller';
    }
    return $args;
}, 10, 2);

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

23 нояб. 2018 г. 12:09:29
0

Вы можете получить все зарегистрированные меню и их данные.

Обновленный код:

function get_menu() {
    # Замените 'menu' на ваш собственный слаг навигации.
    $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',
    ) );
} );

Затем вы можете получать данные из

27 окт. 2023 г. 14:49:21