รับเมนูการนำทาง WP จาก REST API V2


14

ฉันพยายามรับเมนูการนำทางจากการตอบกลับ JSON โดยใช้ปลั๊กอินWP REST API v2

ไม่มีส่วนขยายปลั๊กอินเมนูนำทางสำหรับ REST API v2แต่สำหรับ V1 เท่านั้น

จากประเภทโพสต์ WordPress ของ codex ฉันได้เรียนรู้ว่าเมนูนำทางนั้นถือว่าเป็นประเภทโพสต์

จาก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

คำตอบ:



48

เนื่องจากฉันไม่ชอบตัวเองเมื่อคำตอบที่ดีที่สุดคือ "ติดตั้งปลั๊กอิน 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 ยังดีถ้าคุณต้องการประมวลผลข้อมูลก่อนส่งไปยังแอปพลิเคชันของคุณ


4
ขอบคุณสำหรับการแบ่งปันวิธีแก้ปัญหาของคุณมีมากขึ้นกว่าเพียงแค่การเชื่อมโยงปลั๊กอิน ;-) มันจะดีกว่า แต่คำนำหน้าชื่อฟังก์ชั่นของคุณหรือการใช้ namespace เพื่อหลีกเลี่ยงการปะทะกันชื่อเป็นไปได้เป็นget_menu()ทั่วไปสวย
Birgire

สุดยอดผู้คนไม่รู้ตัวว่าคนส่วนใหญ่ติดตั้งปลั๊กอิน 30 ถึง 70 เรียบร้อยแล้ว พวกเขายังมีปลั๊กอินเพื่อให้คนอื่นปิดการใช้งาน! มันบ้า ฉันคิดว่าฉันจะติดตั้งปลั๊กอินเพื่อเก็บกระทู้นี้
Ignacio Bustos

มันจะออกเฉพาะfalse
moesphemie

1

@Liren คำตอบทำงานได้ดี อย่างไรก็ตามผู้เริ่มต้นไม่กี่คนอาจไม่สามารถปรับเส้นทางได้ นี่คือรหัสที่ทำงานได้ดีกับ WordPress Rest API v2 ที่มีการปรับเปลี่ยนขั้นต่ำ

แทนที่ชื่อเมนูของคุณเฉพาะในฟังก์ชั่นwp_get_nav_menu_items () หากชื่อเมนูและกระสุนไม่ทำงาน (Return false) ให้ใช้ ID เมนู (ปรากฏใน 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 เล็กน้อย นอกจากนี้ยัง alters เริ่มต้นควบคุมโพสต์ REST เพื่อแสดงการส่งออกค่อนข้างคล้ายกันในส่วนที่เหลือตามที่อธิบายไว้ในคำตอบของ Liren แม้ว่าถัดจากนั้นยังทำหน้าที่ควบคุมการโพสต์ประเภท 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',
    ) );
} );

เช่นนี้มันใช้งานได้สำหรับฉัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.