เมื่อใดที่คุณควรใช้ WP_Query vs query_posts () vs get_posts ()


418

ดูเหมือนว่าครึ่งหนึ่งของบทเรียนในที่Codexและรอบการใช้ blogosphere ครึ่งใช้query_posts() WP_Queryตกลงคืออะไร?


คำตอบ:


667
  • query_posts()นั้นง่ายเกินไปและเป็นวิธีที่มีปัญหาในการแก้ไขคิวรีหลักของเพจโดยแทนที่ด้วยเคียวรีใหม่ของเคียวรี มันไม่มีประสิทธิภาพ (เรียกใช้แบบสอบถาม SQL อีกครั้ง) และจะล้มเหลวทันทีในบางสถานการณ์ (โดยเฉพาะอย่างยิ่งเมื่อจัดการกับการแบ่งหน้าโพสต์) รหัส WP ที่ทันสมัยใด ๆ ควรใช้วิธีการที่เชื่อถือได้มากขึ้นเช่นการใช้pre_get_postshook สำหรับจุดประสงค์นี้ TL; DR ไม่ได้ใช้ query_posts () เคย

  • get_posts() มีลักษณะคล้ายกันมากในการใช้งานและยอมรับอาร์กิวเมนต์เดียวกัน (ด้วยความแตกต่างบางอย่างเช่นค่าเริ่มต้นที่แตกต่างกัน) แต่ส่งกลับอาร์เรย์ของโพสต์ไม่ได้แก้ไขตัวแปรทั่วโลกและปลอดภัยที่จะใช้ที่ใดก็ได้

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


8
@jjeaton query_posts()เป็นฟังก์ชั่น wrapper ขนาดเล็กสำหรับWP_Queryสิ่งพิเศษอย่างเดียวที่มันทำ (ตามผังงาน) คือการเขียนทับทั่วโลก$wp_query
Rarst

7
@jjeaton การแทนที่query_posts()ด้วยWP_Queryจะไม่ทำให้ประสิทธิภาพในการทำงานแตกต่างไปแบบสอบถามของหน้าดั้งเดิมจะยังคงทำงานเนื่องจากเป็นส่วนหนึ่งของโหลดหลัก ข้อความค้นหาเหล่านั้นจะทำงานแม้ว่าไฟล์เทมเพลตของคุณจะไม่วนซ้ำก็ตาม
Rarst

116
ไม่สามารถกำจัดความรู้สึกที่ว่านี่เป็นโพสต์ที่สุภาพและอัปยศที่สุดใน WPSE ควรอยู่ใน Codex เช่นกัน
ไกเซอร์

8
ฉันจะเพิ่มคำอธิบายที่ชัดเจนที่สุดของปัญหา "ประสิทธิภาพของ query_posts ()": การใช้ query_posts () หรือ WP_Query ภายในไฟล์เทมเพลตจะมีต้นทุนการดำเนินการเท่ากัน: แบบสอบถามที่คุณเพิ่งดำเนินการ ปัญหาที่กล่าวถึงในบทความตัวแปลงสัญญาณคือถ้าคุณต้องการแทนที่คิวรีจริงคุณควรทำเช่นนั้นโดยการกรอง query_posts เดิม () ด้วยตัวกรอง 'parse_query' ด้วยวิธีนี้คุณจะมีเพียงแบบสอบถามที่เป็นต้นฉบับและเป็นที่ต้องการเท่านั้นแทนที่จะทำแบบสอบถามที่สองเพื่อแทนที่มันอย่างเชื่องช้า query_posts () ไม่เคยเป็นทาง !! ไม่เคย!
jerclarke

22
มีคำอธิบายที่น่าประหลาดใจที่น่าประหลาดใจเกี่ยวกับ query_posts ที่เขียนโดย John James Jacoby ในบล็อก developer.wordpress.com ซึ่งทำให้คำตอบเหล่านี้หมดไป จุดหลัก: query_postsไม่ได้แก้ไขลูปหลักเลยมันจะแทนที่มันหลังจากที่มันได้ทำงานไปแล้ว วิธีที่ดีที่สุดในการแก้ไขลูปหลักคือผ่านpre_get_postsตัวกรอง developer.wordpress.com/2012/05/14/…
Dan Gayle

65

query_posts- query_postsคุณจะไม่เคยใช้ นอกเหนือจากสิ่งที่ @Rarst ได้กล่าวไปแล้วปัญหาใหญ่ที่เกิดขึ้นกับquery_postsมันคือมันทำลายวัตถุแบบสอบถามหลัก (เก็บไว้ใน$wp_query) ปลั๊กอินและรหัสที่กำหนดเองจำนวนมากอาศัยวัตถุแบบสอบถามหลักดังนั้นการทำลายวัตถุแบบสอบถามหลักหมายความว่าคุณกำลังทำลายฟังก์ชันการทำงานของปลั๊กอินและรหัสที่กำหนดเอง ฟังก์ชั่นดังกล่าวเพียงตัวเดียวคือฟังก์ชั่นการให้เลขหน้าที่สำคัญทั้งหมดดังนั้นหากคุณแยกเคียวรีหลักออก

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

var_dump( $wp_query );
query_posts( '&posts_per_page=-1' );
var_dump( $wp_query );

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

ในสาระสำคัญWP_Queryถูกใช้โดยการสืบค้นหลักและยังใช้โดยget_postsแต่ถึงแม้ว่าการget_posts()ใช้WP_Queryมีความแตกต่างเล็กน้อย

  • get_postsWP_Queryจะเร็วกว่า มาร์จิ้นขึ้นอยู่กับจำนวนโพสต์ทั้งหมดของเว็บไซต์ เหตุผลสำหรับสิ่งนี้คือget_postsส่งผ่าน'no_found_rows' => trueค่าเริ่มต้นWP_Queryที่การข้าม / แบ่งการแบ่งหน้าตามกฎหมาย ด้วย'no_found_rows' => true, WP_Queryได้รับจำนวนโพสต์สอบถามแล้ว bails ออกที่โดยค่าเริ่มต้นมันต่อไปค้นหาโพสต์ทั้งหมดที่ตรงกับแบบสอบถามเพื่อคำนวณเลข

    ด้วยเหตุผลนี้get_posts()ควรใช้สำหรับข้อความค้นหาที่ไม่ใส่หน้าเท่านั้น การแบ่งหน้าget_postsเป็นหนึ่งในเรื่องใหญ่ WP_Queryควรใช้สำหรับการค้นหาที่มีเลขหน้าทั้งหมด

  • get_posts()ไม่ได้รับอิทธิพลจากposts_*ตัวกรองที่WP_Queryได้รับอิทธิพลจากตัวกรองเหล่านี้ เหตุผลก็คือget_postsโดยค่าเริ่มต้น'suppress_filters' => trueจะส่งผ่านไปยังWP_Query

  • get_postsมีคู่ของพารามิเตอร์เพิ่มเติมเช่นinclude, exclude, และnumberposts categoryพารามิเตอร์เหล่านี้ไม่ได้รับการเปลี่ยนเป็นพารามิเตอร์ที่ถูกต้องสำหรับก่อนที่จะถูกส่งผ่านไปยังWP_Query ได้รับการเปลี่ยนแปลงเข้าสู่, เข้า, เข้าและออกเป็น เพียงบันทึกทั้งหมดของพารามิเตอร์ที่สามารถส่งผ่านไปยังทำงานร่วมกับคุณสามารถละเลยและไม่ใช้พารามิเตอร์เริ่มต้นของWP_Queryincludepost__inexcludepost__not_incategorycatnumberpostsposts_per_pageWP_Queryget_postsget_posts

  • get_postsคืนค่า$postsคุณสมบัติของWP_Querywhile WP_Queryส่งคืนวัตถุที่สมบูรณ์ วัตถุนี้มีประโยชน์มากเมื่อมันมาถึงเงื่อนไขการแบ่งหน้าและข้อมูลที่เป็นประโยชน์อื่น ๆ ที่สามารถใช้ภายในวง

  • get_postsไม่ใช้ลูป แต่เป็นforeachลูปเพื่อแสดงโพสต์ โดยค่าเริ่มต้นจะไม่มีแท็กแม่แบบ setup_postdata( $post )จะต้องใช้เพื่อให้แท็กแม่แบบพร้อมใช้งาน WP_Queryใช้ห่วงและแท็กแม่แบบที่มีอยู่โดยค่าเริ่มต้น

  • get_postsผ่าน'ignore_sticky_posts' => 1ไปWP_Queryดังนั้นget_postsโดยค่าเริ่มต้นจะไม่สนใจโพสต์เหนียว

จากข้างต้นไม่ว่าจะใช้get_postsหรือWP_Queryขึ้นอยู่กับคุณและสิ่งที่คุณต้องการจากแบบสอบถาม ข้างต้นควรแนะนำคุณในการเลือกของคุณ


1
ฉันหวังว่าฉันจะได้คำตอบที่ชื่นชอบ สิ่งนี้อธิบายได้มาก
Patrik Alienus

1
คำอธิบายที่ดี! ควรใช้ "get_posts () สำหรับข้อความค้นหาที่ไม่ใส่หน้าเท่านั้นการสร้างหน้า get_posts นั้นเป็นเรื่องใหญ่อย่างหนึ่ง WP_Query ควรใช้สำหรับข้อความค้นหาที่มีเลขหน้าทั้งหมด" โดยทั่วไปแล้วทุกคนต้องการรู้ imo
Bullyen

32

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

query_posts('meta_key=color&meta_value=blue'); 

บนมืออื่น ๆ ที่WP_Queryมีมากขึ้นของเครื่องมืออเนกประสงค์และเป็นมากขึ้นเช่นการเขียนคำสั่ง MySQL โดยตรงกว่าquery_posts()คือ นอกจากนี้คุณยังสามารถใช้งานได้ทุกที่ (ไม่ใช่แค่ในลูป) และไม่รบกวนการทำงานของโพสต์ที่กำลังทำงานอยู่

ฉันมักจะใช้WP_Queryบ่อยขึ้นตามที่เกิดขึ้น จริงๆมันจะลงมาที่กรณีเฉพาะของคุณ


15

query_posts()มีเพียงไม่มีความจำเป็นต้องใช้ สิ่งที่มันทำคือการสร้างวัตถุ WP_Query ขึ้นใหม่และกำหนดใหม่ให้กับวัตถุglobal wp_queryนั้น

สำหรับการอ้างอิงต่อไปนี้เป็นquery_posts()ฟังก์ชั่นที่ เกิดขึ้นจริง

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

ยกตัวอย่างวัตถุ WP_Query ของคุณเองหากคุณต้องการสร้างสคริปต์คิวรีที่กำหนดเองในเชิงลึก หรือใช้get_posts()หากสิ่งที่คุณต้องทำคือการปรับแต่งแสงที่นี่และที่นั่น

ไม่ว่าในกรณีใดฉันขอแนะนำให้คุณทำสิ่งที่ชอบและwp_includes/query.phpเข้าWP_Queryเรียนในชั้นเรียน


14

ตรวจสอบให้แน่ใจว่าคุณใช้ wp_reset_query()หลังจากใช้query_posts()เพราะจะมีผลต่อผลลัพธ์แบบสอบถามอื่น ๆ ด้วย


10

ถ้าฉันจำการอ่านได้ถูกต้องโดยหลักแล้ว "การวนซ้ำ" กำลังทำWP_Queryอยู่ในไฟล์หลัก แต่ในวิธีที่เข้าใจง่ายกว่า


6
  • query_posts () : อาจใช้ในกรณีเดียวเท่านั้นหากคุณต้องการแก้ไขคิวรีหลัก มันตั้งค่าตัวแปรส่วนกลางจำนวนมาก
  • get_posts () : มันคล้ายกันมากในกลศาสตร์และยอมรับอาร์กิวเมนต์เดียวกัน แต่ส่งคืนอาร์เรย์ของโพสต์
  • WP_Query : คุณสามารถสร้างและทำงานกับวัตถุของมันเอง บิตที่ซับซ้อนมากขึ้นข้อ จำกัด น้อยกว่ามันปลอดภัยที่จะใช้ทุกที่

-6

ฉันว่าจะไม่ใช้get_posts()ในปลั๊กอิน มันกำหนดตัวกรองที่เข้มงวดมากในบางกรณี (ชุดของsuppress_filters, ignore_sticky_postsฯลฯ ) และอาจจะใช้ในรูปแบบเฉพาะเมื่อคุณต้องการทำสิ่งที่รวดเร็ว

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