การสร้างวิดเจ็ตการค้นหาโดยใช้ WordPress REST API

เผยแพร่แล้ว: 2016-03-28

นักพัฒนา WordPress จะทราบดีว่า REST API มีมาระยะหนึ่งแล้ว แต่เมื่อปลายปีที่แล้วได้มีการรวมเข้ากับแกนหลัก ซึ่งหมายความว่าขณะนี้สามารถใช้ประโยชน์ได้ในวิดเจ็ตและปลั๊กอิน

ในบทความนี้ เราจะสร้างวิดเจ็ตการค้นหาแบบง่ายที่มีความแตกต่าง การใช้ WordPress REST API วิดเจ็ตนี้จะค้นหาเว็บไซต์ WordPress ภายนอกและแสดงผลลัพธ์ในวิดเจ็ต

โพสต์นี้ต่อจากบทความล่าสุดของฉันเกี่ยวกับ สิ่งที่คุณต้องรู้เกี่ยวกับ WordPress REST API

สร้างฐานความรู้ - วิธีง่ายๆ!

สร้างฐานความรู้ที่สามารถค้นหาได้และช่วยให้ลูกค้าของคุณช่วยเหลือตนเอง

รับปลั๊กอิน

การสร้างปลั๊กอินวิดเจ็ต

ตามบทความที่แล้ว จะถือว่ามีความรู้พื้นฐานเกี่ยวกับการสร้างปลั๊กอินและวิดเจ็ต หากคุณไม่แน่ใจ มีบางสิ่งที่คุณแนะนำให้อ่านที่ส่วนท้ายของบทความนี้

มาดูปลั๊กอินที่เราสร้างไว้ในบทความที่แล้วกัน รหัสของคุณควรมีลักษณะดังนี้:


/**
* Plugin Name: KB - REST API Widget
* Author: Kirsty Burgoine
*/

class REST_API_Widget extends WP_Widget {

/**
* Sets up the widgets name etc
*/
public function __construct() {
    $widget_ops = array(
        'classname' => 'rest-api-widget',
        'description' => 'A REST API widget that pulls posts from a different website'
    );
    parent::__construct( 'rest_api_widget', 'REST API Widget', $widget_ops );
}

/**
* Outputs the content of the widget
*
* @param array $args
* @param array $instance
*/
public function widget( $args, $instance ) {
    // outputs the content of the widget

    $response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2 /ht_kb/' );
    if( is_wp_error( $response ) ) {
        return;
    }

    $posts = json_decode( wp_remote_retrieve_body( $response ) );

    if( empty( $posts ) ) {
        return;
    }

    echo $args['before_widget'];
    if( !empty( $instance['title'] ) ) {
        echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) . $args['after_title'];
    }

    // Main Widget Content Here
    if( !empty( $posts ) ) {
        echo '<ul>';
        foreach( $posts as $post ) {
            echo '<li><a href="' . $post->link. '">' . $post->title->rendered . '</a></li>';
        }
        echo '</ul>';
    }
    echo $args['after_widget'];
}

/**
* Outputs the options form on admin
*
* @param array $instance The widget options
*/
public function form( $instance ) {
    //outputs the options form on admin
    $title = ( !empty( $instance['title'] ) ) ? $instance['title'] : '';
    ?>
         <label for="<?php echo $this->get_field_name( 'title' ); ?>">Title: </label>
         <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" /> 
    <?php
}
}//end class
add_action( 'widgets_init', function(){
register_widget( 'REST_API_Widget' );
});

โดยพื้นฐานแล้ว เราได้สร้างปลั๊กอินใหม่ ในปลั๊กอินนั้น เราได้สร้างวิดเจ็ตที่แสดงรายการโพสต์ที่กำหนดเองจากฐานความรู้ Heroic จากเว็บไซต์อื่น

สิ่งที่เราจะทำตอนนี้คือแก้ไขเพื่อสร้างคุณลักษณะการค้นหาด้วย

ขั้นตอนที่ 1: แก้ไขข้อความค้นหาพื้นฐานเพื่อให้ได้ผลลัพธ์ที่แตกต่างกัน

ในบทความที่แล้ว คุณจะจำได้ว่าเราได้พูดถึงวิธีรับรายการโพสต์และวิธีเปลี่ยนพารามิเตอร์เพื่อให้เราได้รับประเภทโพสต์ที่กำหนดเองของฐานข้อมูลความรู้แทน

การเรียนรู้อาจไม่น่าแปลกใจเท่าไร แต่นั่นไม่ใช่ทั้งหมดที่เราสามารถทำได้ด้วยวิธี GET ด้วยการใช้พารามิเตอร์การกรอง เราสามารถใช้อาร์กิวเมนต์ใดๆ ที่มีอยู่ได้เมื่อเรียก WP_Query ตัวอย่างเช่น หากเราต้องการเปลี่ยนจำนวนโพสต์ที่แสดง คุณสามารถเพิ่ม:


/posts?filter[posts_per_page]=5

การโทรทางไกลมีลักษณะดังนี้:


$response = wp_remote_get( 'http://website-with -api.com.com/wp-json/wp/v2/posts?filter[posts_per_page]=5' );

หรือถ้าเราต้องการแสดงโพสต์แบบสุ่มเพียงโพสต์เดียว เราสามารถเพิ่ม:


/posts?filter[orderby]=rand&filter[posts_per_page]=1

และนี่ก็เหมือนกันสำหรับพารามิเตอร์การค้นหา ใน WP Query มาตรฐาน พารามิเตอร์จะมีลักษณะดังนี้:


's' => 'keyword'

ดังนั้น การโทรทางไกลของเราต้องมีลักษณะดังนี้:


$response = wp_remote_get( 'http://website-with -api.com.com/wp-json/wp/v2/posts?filter[s]=keyword');

มันค่อนข้างง่ายเมื่อคุณได้แปลงพารามิเตอร์จาก WP_Query เป็นสตริง URL ของ API

สำหรับรายละเอียดทั้งหมดเกี่ยวกับพารามิเตอร์ที่ใช้ได้ โปรดดูที่ WP_Query codex guide

เราไม่ได้ต้องการค้นหาโพสต์มาตรฐาน แต่เราต้องการค้นหาประเภทโพสต์ที่กำหนดเองของฐานข้อมูลความรู้ อย่างไรก็ตาม ตามที่เราเห็นในบทความก่อนหน้านี้ การทำเช่นนี้ทำได้ง่ายเพราะเราทำให้โพสต์ประเภทที่กำหนดเองของเราเป็นแบบสาธารณะได้โดยการเพิ่มตัวกรอง ดังนั้น สิ่งที่เราต้องทำที่นี่คือสอบถามประเภทโพสต์ที่กำหนดเองของฐานข้อมูลความรู้โดยสลับ /posts/ ด้วยชื่อของประเภทโพสต์ที่กำหนดเอง ในกรณีนี้ /ht_kb/ การโทรทางไกลจะมีลักษณะดังนี้:


$response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb?filter[s]=keyword' );

ขั้นตอนที่ 2: ช่องค้นหาและผลลัพธ์การปรับแต่ง

ตอนนี้ เราได้ดูการแก้ไขข้อความค้นหาเพื่อกรองตามข้อความค้นหาที่กำหนด ขั้นตอนต่อไปคือการสร้างวิธีเพื่อให้ได้ข้อความค้นหานั้น

ประการแรก เราต้องเพิ่มช่องค้นหาให้กับปลั๊กอิน เนื่องจากนี่เป็นเพียงแบบฟอร์มการค้นหาทั่วไป เราจึงสามารถใช้ฟังก์ชัน get_search_form() ที่ WordPress ตั้งค่าไว้แล้ว แทนที่จะสร้างแบบฟอร์มการค้นหาแยกต่างหาก

ในไฟล์ปลั๊กอิน ให้มองหาบรรทัดที่มีความคิดเห็น // เนื้อหาวิดเจ็ตหลักที่นี่ภายในฟังก์ชันวิดเจ็ตของคุณและเพิ่ม get_search_form(); และแก้ไขด้านล่างโดยตรงเพื่อให้มีลักษณะดังนี้:


// Main Widget Content Here
get_search_form();

if( !empty( $posts ) ) {
    echo '<ul>';
    foreach( $posts as $post ) {
        echo '<li><a href="' . $post->link. '">' . $post->title->rendered . '</a></li>';
    }
    echo '</ul>';
}

ตอนนี้เมื่อเราดูวิดเจ็ตบนหน้า คุณจะเห็นแบบฟอร์มการค้นหามาตรฐานและรายการโพสต์จากฐานความรู้ด้านล่าง

มาตรฐานการค้นหาวิดเจ็ต

เรารู้จากการใช้ get_search_form(); เมื่อเราค้นหาบางสิ่ง พารามิเตอร์การค้นหาจะปรากฏใน url ดังนี้:


/?s=test

' เป็นพารามิเตอร์ $_GET และ 'ทดสอบ' เป็นข้อความค้นหาของคุณ ดังนั้น เหลือเพียงหยิบคำค้นหาจาก URL และใช้ในการตอบกลับดังนี้:


if ( isset ( $_GET['s'] ) && !empty( $_GET['s'] ) ) {
    $response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb?filter[s]='.$_GET['s'] );
}
else {
    $response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb/' );
}

รหัสนี้ทำอะไรได้บ้าง ตรวจสอบว่า $_GET['s'] ถูกตั้งค่าและไม่ว่างเปล่าหรือไม่ หากมี/เป็น แสดงว่าคุณรวมไว้ในคำตอบของคุณ หากไม่ แสดงว่าไม่มีการค้นหาและคุณต้องการแสดงโพสต์ในฐานข้อมูลความรู้ทั้งหมดตามปกติ

รายละเอียดเพิ่มเติมเกี่ยวกับฟังก์ชัน get_search_form() สามารถพบได้ที่นี่

นี่คือจุดที่เราคาดหวังว่าบทความนี้จะจบลงใช่ไหม ท้ายที่สุด เราได้ตั้งค่าแบบฟอร์มการค้นหาที่ค้นหาโพสต์บนเว็บไซต์ภายนอกโดยใช้ WordPress REST API แล้วส่งคืนผลลัพธ์เหล่านั้นตามพารามิเตอร์การค้นหา อย่างไรก็ตาม…

ขั้นตอนที่ 3: การแก้ไขผลลัพธ์ที่แสดง

หากเราทดสอบวิดเจ็ตการค้นหาใหม่ เราจะเห็นว่าวิดเจ็ตทำงานตามที่คาดไว้ อย่างไรก็ตาม วิดเจ็ตจะแสดงผลลัพธ์จากเว็บไซต์ปัจจุบันในเนื้อหาของหน้าหลักด้วย

ค้นหาเทมเพลตผลลัพธ์
วิดเจ็ตการค้นหาแสดงผลลัพธ์สำหรับ 'ทดสอบ' และหน้าเปลี่ยนเส้นทางไปยังเทมเพลตผลการค้นหา

นี่เป็นเพราะระบบเทมเพลตของ WordPress WordPress ใช้สตริงการสืบค้นเพื่อกำหนดเทมเพลตหรือชุดเทมเพลตที่จะใช้ เนื่องจากเมื่อส่งแบบฟอร์มการค้นหาจะเพิ่มพารามิเตอร์ 's' ลงใน URL เป็นการบอกให้ WordPress ทำการค้นหาและเปลี่ยนเส้นทางไปยังหน้าผลการค้นหา ซึ่งในธีม TwentySixteen คือ search.php

สำหรับข้อมูลเพิ่มเติม โปรดดูเอกสารลำดับชั้นเทมเพลต

เป็นสิ่งที่ดีถ้าเราต้องการค้นหาบนเว็บไซต์ท้องถิ่นและเว็บไซต์ภายนอกโดยใช้ API ในเวลาเดียวกันเพราะผลลัพธ์ของทั้งสองจะแสดงขึ้น อย่างไรก็ตาม ในกรณีนี้ เราไม่ต้องการทำเช่นนั้น เราต้องการให้ผลลัพธ์ส่งคืนโดยใช้ API เพื่อแสดงในวิดเจ็ตเท่านั้น หน้าหลักไม่ควรได้รับผลกระทบ

มีหลายวิธีในการทำเช่นนี้ สำหรับตัวอย่างนี้ เราจะมาดูวิธีการแก้ไข get_search_form(); ฟังก์ชั่นที่จะไม่ใช้ 's' เป็นพารามิเตอร์การค้นหาอีกต่อไป แต่จะเปลี่ยนเป็น 'a' เพื่อข้ามปัญหา

ขั้นตอนแรกคือการปรับเปลี่ยนแบบฟอร์มโดยการสร้างฟังก์ชันใหม่


function api_search_form( $form ) {

 $form = '<form role="search" method="get" class="search-form" action="' . home_url( '/' ) . '">
         <label>
             <span class="screen-reader-text">' . _x( 'Search for:', 'label' ) . '</span>
             <input type="search" class="search-field" placeholder="' . esc_attr_x( 'Search …', 'placeholder' ) .'" value="' . get_search_query() . '" name="a" title="' . esc_attr_x( 'Search for:', 'label' ) .'" />
         </label>
         <button type="submit" class="search-submit"><span class="screen-reader-text">Search</span></button>
         </form>';

 return $form;
}

 add_filter( 'get_search_form', 'api_search_form', 100 );

ฟังก์ชันนี้ค่อนข้างเรียบง่าย โดยพื้นฐานแล้วจะเป็นรูปแบบใหม่ที่จะใช้แทนรูปแบบเริ่มต้น หากเราดูที่ชุดรูปแบบอ้างอิง TwentySixteen และตรวจสอบแบบฟอร์มการค้นหาที่มีอยู่ เราทราบว่าความแตกต่างเพียงอย่างเดียวในรหัสคือชื่อของอินพุตการค้นหา เดิมทีมันคือ 'name=s' และตอนนี้คือ 'name=a' การดำเนินการนี้จะลบพารามิเตอร์ 's' ออกจาก URL

หมายเหตุ: ด้วยวิธีนี้ เราแก้ไขแบบฟอร์มการค้นหาหลักเพื่อค้นหาโดยใช้ API แทนการค้นหาเว็บไซต์โฮสต์ ดังนั้น จึงเป็นสิ่งสำคัญที่จะต้องพิจารณาว่า หากเราใช้แบบฟอร์มการค้นหาหลักที่อื่นบนเว็บไซต์ จะไม่เปลี่ยนเส้นทางไปยังผลการค้นหาจากเว็บไซต์ของโฮสต์เว็บไซต์อีกต่อไป เพื่อให้มีการค้นหาที่แตกต่างกันสองครั้ง วิธีแก้ปัญหาที่ง่ายที่สุดคือการเพิ่มโค้ดสำหรับแบบฟอร์มใหม่นี้โดยตรงในวิดเจ็ต แทนที่จะแก้ไข get_search_form();

ขั้นตอนสุดท้ายคือการเพิ่มตัวกรอง สิ่งนี้บอกให้ WordPress แทนที่แบบฟอร์มที่มีอยู่ด้วยแบบฟอร์มนี้แทน เราสามารถวางบล็อคโค้ดทั้งหมดลงในไฟล์ปลั๊กอินหลังคลาสวิดเจ็ต ซึ่งอาจรวม functions.php ของธีมแทน แต่การรวมไว้ในปลั๊กอิน หมายความว่าการเปลี่ยนแปลงในแบบฟอร์มจะเกิดขึ้นต่อเมื่อเปิดใช้งานปลั๊กอินเท่านั้น

ตอนนี้เราได้เปลี่ยนชื่ออินพุตเป็น 'a' แล้ว เราต้องเปลี่ยนพารามิเตอร์การค้นหาที่แท้จริงด้วย พารามิเตอร์จะปรากฏใน URL เป็น: /?a=test แทนที่จะเป็น /?s=test ดังนั้นจึงลบส่วนของสตริงข้อความค้นหาที่บอก WordPress ว่าควรเปลี่ยนเส้นทางไปยังเทมเพลตผลการค้นหา

เพื่อให้คุณสามารถค้นหาโดยใช้พารามิเตอร์ใหม่ อัปเดตโค้ดที่เขียนไว้ก่อนหน้านี้สำหรับการโทรระยะไกลเพื่อใช้พารามิเตอร์ 'a' แทน 's'

ตอนนี้ควรมีลักษณะดังนี้:


if ( isset ( $_GET['a'] ) && !empty( $_GET['a'] ) ) {
    $response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb?filter[s]='.$_GET['a'] );
} else {
    $response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb/' );
}

ขอให้สังเกตว่าแม้ว่าพารามิเตอร์การค้นหาใน $_GET จะเปลี่ยนไป แต่สิ่งนี้จะไม่เปลี่ยนตัวกรองในการสืบค้นจริง เนื่องจาก WP Query มาตรฐานสำหรับการค้นหายังคงเป็น 's'

เมื่อเราทดสอบวิดเจ็ต เราควรจะสามารถค้นหาบทความฐานข้อมูลองค์ความรู้บนเว็บไซต์ภายนอกของคุณ และส่งคืนผลลัพธ์โดยไม่ถูกเปลี่ยนเส้นทางไปยังหน้าผลการค้นหา

วิดเจ็ตการค้นหาแสดงผลลัพธ์สำหรับ 'ทดสอบ' โดยไม่ต้องเปลี่ยนเส้นทางหน้า
วิดเจ็ตการค้นหาแสดงผลลัพธ์สำหรับ 'ทดสอบ' โดยไม่ต้องเปลี่ยนเส้นทางหน้า

รหัสเต็มสำหรับวิดเจ็ตมีลักษณะดังนี้:


/**
 * Plugin Name: KB - REST API Widget
 * Author: Kirsty Burgoine
*/

class REST_API_Widget extends WP_Widget {

 /**
 * Sets up the widgets name etc
 */
 public function __construct() {
     $widget_ops = array( 
     'classname' => 'rest-api-widget',
     'description' => 'A REST API widget that pulls posts from a different website');

     parent::__construct( 'rest_api_widget', 'REST API Widget', $widget_ops );
 }



 /**
 * Outputs the content of the widget
 *
 * @param array $args
 * @param array $instance
 */
 public function widget( $args, $instance ) {
     // outputs the content of the widget
     if ( isset ( $_GET['a'] ) && !empty( $_GET['a'] ) ) {
         $response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb?filter[s]='.$_GET['a'] );
     } else {
         $response = wp_remote_get( 'http://website-with-api.com/wp-json/wp/v2/ht_kb/' );
     }

     if( is_wp_error( $response ) ) {
         return;
     }

     $posts = json_decode( wp_remote_retrieve_body( $response ) );

     if( empty( $posts ) ) {
         return;
     }

     echo $args['before_widget'];
     if( !empty( $instance['title'] ) ) {
         echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) . $args['after_title'];
     }
 
     // Main Widget Content Here
     get_search_form();

     if( !empty( $posts ) ) { 
         echo '<ul>';
         foreach( $posts as $post ) {
             echo '<li><a href="' . $post->link. '">' . $post->title->rendered . '</a></li>';
         }
         echo '</ul>'; 
     }
     echo $args['after_widget'];
 }

 /**
 * Outputs the options form on admin
 *
 * @param array $instance The widget options
 */
 public function form( $instance ) {
     // outputs the options form on admin

     $title = ( !empty( $instance['title'] ) ) ? $instance['title'] : '';
     ?>
         <label for="<?php echo $this->get_field_name( 'title' ); ?>">Title: </label>
         <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" 
      name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
     <?php
     }
}

function api_search_form( $form ) {

 $form = '<form role="search" method="get" class="search-form" action="' . home_url( '/' ) . '">
         <label>
             <span class="screen-reader-text">' . _x( 'Search for:', 'label' ) . '</span>
             <input type="search" class="search-field" placeholder="' . esc_attr_x( 'Search …', 'placeholder' ) .'" value="' . get_search_query() . '" name="a" title="' . esc_attr_x( 'Search                 for:', 'label' ) .'" />
         </label>
         <button type="submit" class="search-submit"><span class="screen-reader-text">Search</span></button>
         </form>';

 return $form;
}
add_filter( 'get_search_form', 'api_search_form', 100 );


add_action( 'widgets_init', function(){
 register_widget( 'REST_API_Widget' );
});

นี่เป็นการใช้งานวิดเจ็ตการค้นหาแบบกำหนดเองที่ง่ายมากโดยใช้ REST API ดังที่แสดงไว้ก่อนหน้านี้ เราสามารถเพิ่มตัวกรองเพิ่มเติมในการค้นหาเพื่อจำกัดจำนวนผลการค้นหาหรือลำดับที่จะแสดง คุณสามารถเลือกที่จะแสดงข้อมูลเพิ่มเติมในวิดเจ็ต เช่น ข้อความค้นหาและจำนวนผลลัพธ์ หรือ หากคุณรู้จัก jQuery / Javascript คุณสามารถใช้สิ่งนี้เพิ่มเติมและเพิ่มเอฟเฟกต์ AJAX ที่ดี เพื่อให้ผลลัพธ์ถูกส่งกลับโดยไม่จำเป็นต้องรีเฟรชหน้า

อ่านเพิ่มเติม:

  • วิดเจ็ต API (WordPress Codex)
  • ข้อมูลเบื้องต้นเกี่ยวกับการสร้างวิดเจ็ต WordPress ตัวแรกของคุณ (Tutsplus)
  • วิธีสร้างวิดเจ็ต WordPress แบบกำหนดเอง (WP Beginner)
  • วิธีสร้างปลั๊กอินวิดเจ็ตสำหรับ WordPress (WP Explorer)