从REST API V2获取WP导航菜单


14

我正在尝试使用WP REST API v2插件从JSON响应中获取导航菜单。

没有针对REST API v2的导航菜单插件扩展,仅针对V1。

从Codex WordPress帖子类型中,我了解到导航菜单被视为帖子类型。

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

服务器理解了我的请求,但拒绝提供数据。

问:我该如何解决?


所有这些答案都是可怕的。安装它,扩展它。它应该已经内置,社区应该在GitHub上发布问题。
SacWebDeveloper

Answers:



48

当我的最主要回答是“安装插件X”时,由于我自己不喜欢它,因此这是我的解决方法:

菜单在WP Rest中当前不可用。因此,您需要做的是注册自己的自定义终结点,然后从需要它的应用程序中调用该路由。

因此,您将包括以下内容(在functions.php,plugin中的任何位置):

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中不可用的任何类型的数据。如果您需要在将某些数据发送到应用程序之前对其进行处理,那也很好。


4
感谢您与您分享解决方法,而不仅仅是一个插件链接;-)最好在函数名前加上前缀或使用命名空间,以避免可能的名称冲突,这get_menu()很普遍。
birgire

太棒了,人们并没有意识到大多数人已经安装了30到70个插件。他们甚至有插件来保持停用状态!太疯狂了。我想我要安装一个插件来保持该线程。
伊格纳西奥·布斯托斯

它仅输出false
moesphemie

1

@Liren的答案效果很好。但是,很少有初学者可能无法调整路线。这是经过最少的修改即可与WordPress Rest API v2完美结合代码

仅在wp_get_nav_menu_items()函数中替换菜单名称。如果菜单名称和子菜单不起作用(返回false),请使用菜单ID(在编辑该菜单时在仪表板中可见)。

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',
    ) );
} );

路线网址:

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中显示帖子类型。它还会更改默认的Posts REST控制器,以在REST中显示一些类似的输出,如Liren's answer中所述。尽管除此之外,它还可以完成所有后置类型REST控制器的工作,从而为您提供更多控制和功能。还应将其视为更稳定的选项,因为它不会与其他REST路由冲突,并且最后但并非最不重要的是,它也更方便使用。


0

我同意@Lirens的回答,但是菜单应该通过ID来调用,而不是笨拙。另外,不需要菜单路径前的斜杠。因此,它变得更像这样:

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',
    ) );
} );

这样对我有用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.