从REST API V2获取WP导航菜单

时间:2015-11-20 作者:Murhaf Sousli

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

REST API没有导航菜单插件扩展v2, 但仅适用于V1

来自codexWordPress Post Types, 我了解到导航菜单被视为post类型。

从…起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: How can I fix this?

7 个回复
最合适的回答,由SO网友:Yan Takushevich 整理而成

REST API v2有一个导航菜单插件扩展:https://wordpress.org/plugins/wp-api-menus/

SO网友:Liren

因为我自己也不喜欢上面的答案是“安装插件X”,所以我是这样解决的:

WP Rest中当前没有可用的菜单。所以你需要做的是register your own custom endpoint 然后从需要它的应用程序调用该路由。

因此,您应该包括以下内容(在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中不可用的任何类型的数据。如果在将数据发送到应用程序之前需要处理一些数据,也很好。

SO网友:Deepak Rajpal

@李仁的回答很好。然而,很少有初学者不能调整路线。这是code that works well with WordPress Rest API v2 最小修改量。

仅在中替换菜单名wp_get_nav_menu_items() 作用如果菜单名和slug不起作用(返回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\',
    ) );
} );
路由URL:

https://website.com/wp-json/wp/v2/menu
教程中介绍的更多详细信息:WordPress Rest API – Get Navigational Menu Items

SO网友:Mel Macaluso

我选择了最简单的方法,仍然保持动态,以便您可以获取多个菜单。

/**
 * Returns menu items in a array based on the navigation menu id passed
 *
 * @param object The actual request where parameters can be accessed.
 * @return array The menu items contained in that specific menu
 */
function expose_navigation($request) {
  $id = $request[\'id\'];
  return wp_get_nav_menu_items($id);
}

/**
 * Exposes under /navigation/{id} the menu items in the wp-json api
 *
 * @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}

SO网友:hkc

您需要添加\'show_in_rest\' => true, 注册帖子类型时。

请参见此处的详细信息http://v2.wp-api.org/extending/custom-content-types/

SO网友:Sjoerd Oudman

我同意@Lirens的回答,但菜单应该按ID调用,而不是slug。此外,不需要在菜单路径前加斜杠。所以它变得更像这样:

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\',
    ) );
} );
就像这样,它对我有用。

SO网友:luukvhoudt

我认为插件不应该用于此类任务。而且hkc\'s answer 实际上并没有那么糟糕,只需要进一步的解释就可以了nav_menu_item post类型(用于wp导航菜单的类型)。

这个帖子类型已经注册了,因此我们需要修改它,这可以通过挂接到register_post_type_args 滤器此筛选器允许我们更改特定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\' => __( \'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);
正如您可能已经从上面的代码中注意到的,代码所做的不仅仅是在其余部分中显示post类型。它还更改了默认Posts REST控制器,以在REST中显示类似的输出,如中所述Liren\'s answer. 尽管接下来它也做了所有post类型REST控制器所做的事情,因此为您提供了更多的控制和功能。还可以将其视为一个更稳定的选项,因为它不会与其他REST路线冲突,最后但并非最不重要的是,它还可以更方便地使用。