WordPress Custom Queries – การใช้ WP_Query Class

เผยแพร่แล้ว: 2021-02-06

WordPress มีฟังก์ชันพร้อมใช้งานมากมาย ซึ่งในกรณีส่วนใหญ่สามารถดึงข้อมูลที่จำเป็นจากฐานข้อมูลได้ แต่เมื่อพัฒนาเว็บไซต์ WordPress มีหลายสถานการณ์ที่ตัวกรองหรือการกระทำไม่เพียงพอที่จะบรรลุผลตามที่ต้องการ ในกรณีเหล่านี้ WordPress เสนอวิธีแก้ปัญหาในรูปแบบของคลาส WP_Query

มาดูกันว่าคลาส WP_Query สามารถใช้ได้อย่างไร!

กรณีแบบสอบถามที่กำหนดเอง

หมายเหตุ: บทความนี้อนุมานว่าคุณมีความรู้เกี่ยวกับ PHP และ MySQL/MariaDB plus คุ้นเคยกับการทำงานกับ WordPress

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

สิ่งที่ WP_Query ทำโดยทั่วไปคือให้คุณสามารถดึงเนื้อหาจากฐานข้อมูลของเว็บไซต์ของคุณโดยไม่ต้องใช้คำสั่ง SQL

ในการทำเช่นนี้ สิ่งที่เราต้องทำคือกำหนดอาร์กิวเมนต์ที่สอดคล้องกับความต้องการของเรา จากนั้นวัตถุ WP_Query ใหม่จะถูกสร้างขึ้นและแปลเป็นแบบสอบถาม SQL

ตัวอย่างการใช้ WP_Query

หากเราต้องการแสดงโพสต์จากหมวดหมู่เฉพาะ ภายในเทมเพลตหมวดหมู่อื่น จำเป็นต้องสร้างออบเจกต์การสืบค้นใหม่

สำหรับจุดประสงค์ของตัวอย่างนี้ เราเปิดใช้งานธีม 20 ธีม และสร้าง 2 โพสต์ภายใต้หมวดหมู่ที่ชื่อ 'Category 1' และ 2 โพสต์ภายใต้หมวดหมู่ 'Services'

นอกจากนี้ เราได้สร้างเทมเพลตมุมมองหมวดหมู่แบบกำหนดเองสำหรับโพสต์ 'หมวดหมู่ 1' กระสุนของหมวดหมู่นี้คือ 'category-1' ดังนั้นไฟล์ในโฟลเดอร์ของธีมควรเป็น category-category-1.php category-CATEGORYSLUG.php ซึ่งในกรณีของเราคือ

โปรดวางข้อมูลต่อไปนี้ในไฟล์ category-category-1.php

 <?php /*** Custom Category 1 Template */ get_header(); ?> <main role="main"> <section class="site-content"> <div role="main"> <?php if ( have_posts() ) : ?> <header class="archive-header"> <h3 class="archive-title">Category: <?php single_cat_title( '', true ); ?></h3> </header> <?php while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; endif; ?> </div> </section> </main> <?php get_sidebar(); ?> <?php get_footer(); ?>

ก่อนการวนซ้ำ เราใช้เมธอด have_posts เพื่อตรวจสอบว่ามีโพสต์เพิ่มเติมในลูปหรือไม่

the_post() จำเป็นสำหรับการวนซ้ำโพสต์และบอกให้ WordPress ย้ายไปที่โพสต์ถัดไปของอาร์เรย์โพสต์

ณ จุดนี้ มุมมองส่วนหน้าของหมวดหมู่ ( https://mycompanyname.com/category/category-1/ ) จะเป็นดังนี้:

ฉันรู้ว่าการใช้โค้ดนี้ทำให้เราละเลยที่จะใส่ข้อมูลโพสต์จำนวนมาก แต่สำหรับตัวอย่างนี้ ควรทำให้มันเรียบง่ายและแสดงเฉพาะชื่อโพสต์เท่านั้น

หากต้องการดูคุณสมบัติของวัตถุคิวรีที่ WordPress สร้างขึ้นสำหรับมุมมองนี้ เราเพียงแค่เพิ่มบรรทัดนี้ในโค้ดของเราหลังจุด endif; คำแถลง.

 var_dump ( $wp_query->query_vars );

ตอนนี้ถ้าคุณรีเฟรชหน้าของคุณ คุณจะเป็นข้อมูลนี้ภายใต้รายการโพสต์:

 array(63) { ["category_name"]=> string(10) "category-1" ["error"]=> string(0) "" ["m"]=> string(0) "" ["p"]=> int(0) ["post_parent"]=> string(0) "" ["subpost"]=> string(0) "" ["subpost_id"]=> string(0) "" ["attachment"]=> string(0) "" ["attachment_id"]=> int(0) ["name"]=> string(0) "" ["pagename"]=> string(0) "" ["page_id"]=> int(0) ["second"]=> string(0) "" ["minute"]=> string(0) "" ["hour"]=> string(0) "" ["day"]=> int(0) ["monthnum"]=> int(0) ["year"]=> int(0) ["w"]=> int(0) ["tag"]=> string(0) "" ["cat"]=> int(16) ["tag_id"]=> string(0) "" ["author"]=> string(0) "" ["author_name"]=> string(0) "" ["feed"]=> string(0) "" ["tb"]=> string(0) "" ["paged"]=> int(0) ["meta_key"]=> string(0) "" ["meta_value"]=> string(0) "" ["preview"]=> string(0) "" ["s"]=> string(0) "" ["sentence"]=> string(0) "" ["title"]=> string(0) "" ["fields"]=> string(0) "" ["menu_order"]=> string(0) "" ["embed"]=> string(0) "" ["category__in"]=> array(0) { } ["category__not_in"]=> array(0) { } ["category__and"]=> array(0) { } ["post__in"]=> array(0) { } ["post__not_in"]=> array(0) { } ["post_name__in"]=> array(0) { } ["tag__in"]=> array(0) { } ["tag__not_in"]=> array(0) { } ["tag__and"]=> array(0) { } ["tag_slug__in"]=> array(0) { } ["tag_slug__and"]=> array(0) { } ["post_parent__in"]=> array(0) { } ["post_parent__not_in"]=> array(0) { } ["author__in"]=> array(0) { } ["author__not_in"]=> array(0) { } ["ignore_sticky_posts"]=> bool(false) ["suppress_filters"]=> bool(false) ["cache_results"]=> bool(true) ["update_post_term_cache"]=> bool(true) ["lazy_load_term_meta"]=> bool(true) ["update_post_meta_cache"]=> bool(true) ["post_type"]=> string(0) "" ["posts_per_page"]=> int(10) ["nopaging"]=> bool(false) ["comments_per_page"]=> string(2) "50" ["no_found_rows"]=> bool(false) ["order"]=> string(4) "DESC" }

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

มาดูวิธีที่ WordPress ช่วยให้เราบรรลุเป้าหมายนี้กัน

ฟังก์ชัน query_posts

query_posts() เป็นวิธีแก้ไขข้อความค้นหาหลักที่ WordPress ใช้เพื่อแสดงโพสต์ ทำได้โดยวางแบบสอบถามหลักไว้ด้านใดด้านหนึ่ง และแทนที่ด้วยแบบสอบถามใหม่ คุณสามารถเห็นสิ่งนี้ได้ด้วยตัวคุณเองใน wp-includes/query.php ที่มีการแนะนำ

 function &query_posts($query) { unset($GLOBALS['wp_query']); $GLOBALS['wp_query'] =& new WP_Query(); return $GLOBALS['wp_query']->query($query); }

เราจะพยายามเพิ่มลูปอื่นเพื่อแสดงโพสต์ 'บริการ' โดยเพิ่มบรรทัดต่อไปนี้ใต้ส่วน endwhile; ของลูปมาตรฐานปัจจุบัน

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile;

แล้วคุณล่ะ:

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

ลองแทรก var_dump ( $wp_query->query_vars["category_name"] ); หลังจากแบบสอบถามบริการและรีเฟรชหน้า คุณควรเห็นผลลัพธ์นี้:

 string(8) "services"

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

เพื่อหลีกเลี่ยงความขัดแย้งเหล่านี้และล้างข้อมูลหลังจากการเรียก query_posts ให้โทรไปที่ wp_reset_query() แล้วการสืบค้นหลักเดิมจะถูกกู้คืน ดังนั้นรหัสของคุณควรมีลักษณะดังนี้:

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; wp_reset_query(); var_dump ( $wp_query->query_vars["category_name"] );

เมื่อรีเฟรชหน้าของคุณ คุณจะเห็นว่าหมวดหมู่หน้าแรกกลับมาอยู่ในข้อความค้นหา

 string(10) "category-1"

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

ฟังก์ชัน get_posts()

ผลลัพธ์เดียวกันนี้สามารถทำได้โดยใช้ฟังก์ชัน get_posts() เพื่อดึงข้อมูลอาร์เรย์ของโพสต์ที่ตรงกับเกณฑ์ที่กำหนด

แทนที่ลูปบริการที่แสดงด้านล่าง...

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; wp_reset_query(); var_dump ( $wp_query->query_vars["category_name"] );

…ด้วยสิ่งนี้:

 $my_query = get_posts( array ( 'category' => 17 ) ); foreach($my_query as $post) : setup_postdata($post); the_title( '<h4 class="example"></h4>' ); endforeach; var_dump ( $wp_query->query_vars["category_name"] );

อย่างที่คุณเห็นในครั้งนี้ เราต้องทำงานกับรหัสหมวดหมู่แทนชื่อหมวดหมู่ ตามอาร์กิวเมนต์ get_posts() ที่กำหนดโดย WordPress

สิ่งสำคัญอีกประการที่ควรทราบในที่นี้คือ แม้ว่าเราไม่ได้รีเซ็ตการสืบค้น แต่ผลลัพธ์ var_dump ของหมวดหมู่การสืบค้นยังคงไม่เสียหายและไม่ได้เปลี่ยนเป็น 'บริการ' นั่นเป็นเพราะ get_posts() โดยตัวมันเองไม่ได้เปลี่ยนแปลงการสืบค้นหลัก เราเพิ่งใช้ตัวแปรใหม่ ' $my_query ' เพื่อสร้างอินสแตนซ์ใหม่ของออบเจกต์การสืบค้นโดยไม่ต้องแทนที่

ฟังก์ชัน get_posts( get_posts() ใช้พารามิเตอร์เดียวกับ query_posts() และแนะนำให้ใช้เมื่อคุณต้องการเพิ่มสแตติกลูปแบบกำหนดเองที่ใดก็ได้ในเทมเพลตของคุณ เนื่องจากปลอดภัยและใช้งานง่าย

สร้าง WP_Query Object ใหม่

$wp_query เป็นอ็อบเจ็กต์ของคลาส WP_Query และดึงเนื้อหาฐานข้อมูลที่จำเป็นสำหรับเพจปัจจุบัน การเอาชนะคลาสนี้เป็นวิธีปรับแต่งผลลัพธ์และแสดงเนื้อหาที่แตกต่างกัน

นี่คือส่วนของรหัสที่เราจะใช้:

 $services_query = new WP_Query( 'category_name=services' ); if ( $services_query->have_posts() ) { while ( $services_query->have_posts() ) : $services_query->the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; } wp_reset_postdata(); var_dump ( $wp_query->query_vars["category_name"] );

เราใช้อาร์กิวเมนต์ 'category_name' เพื่อกำหนดตัวบุ้งของหมวดหมู่ที่เราต้องการให้แสดงโพสต์

เราบันทึกวัตถุ new WP_Query( 'category_name=services' ); ในตัวแปร $services_query

จากนั้นเราใช้ while loop เพื่อแสดงเนื้อหาและหลังจากนี้เรารีเซ็ตลูปด้วย wp_reset_postdata(); เพื่อกู้คืนข้อมูลเดิมของแบบสอบถามหลัก

หากคุณต้องการทดลองกับอาร์กิวเมนต์อื่นๆ ของ WP_Query WordPress Class คุณสามารถค้นหารายการทั้งหมดได้ในหน้า WordPress Codex