Khi nào bạn nên sử dụng WP_Query vs query_posts () so với get_posts ()?


Câu trả lời:


667
  • query_posts()quá đơn giản và là một cách có vấn đề để sửa đổi truy vấn chính của trang bằng cách thay thế nó bằng phiên bản mới của truy vấn. Đó là không hiệu quả (chạy lại các truy vấn SQL) và sẽ hoàn toàn thất bại trong một số trường hợp (đặc biệt là thường xuyên khi xử lý phân trang bài viết). Bất kỳ mã WP hiện đại nào cũng nên sử dụng các phương thức đáng tin cậy hơn, như sử dụng pre_get_postshook, cho mục đích này. TL; DR không sử dụng query_posts () bao giờ .

  • get_posts() sử dụng rất giống nhau và chấp nhận cùng một đối số (với một số sắc thái, như các mặc định khác nhau), nhưng trả về một loạt các bài đăng, không sửa đổi các biến toàn cục và an toàn để sử dụng ở bất cứ đâu.

  • WP_Querylà lớp cung cấp năng lượng cho cả hai phía sau hậu trường, nhưng bạn cũng có thể tạo và làm việc với thể hiện của chính nó. Một chút phức tạp hơn, ít hạn chế hơn, cũng an toàn để sử dụng ở bất cứ đâu.


8
@jjeaton query_posts()là chức năng bao bọc nhỏ bé WP_Query, điều duy nhất bổ sung (theo lưu đồ) là ghi đè toàn cầu$wp_query
Rarst

7
@jjeaton Thay thế query_posts()bằng WP_Querysẽ không có sự khác biệt về hiệu suất, truy vấn của trang gốc vẫn sẽ chạy vì đó là một phần của tải trọng cốt lõi. Các truy vấn đó sẽ chạy ngay cả khi tệp mẫu của bạn không có vòng lặp nào cả.
Rarst

116
Không thể thoát khỏi cảm giác rằng đây là bài viết tuyệt vời và được đánh giá cao nhất trên WPSE. Nên ở Codex là tốt.
kaiser

8
Tôi sẽ chỉ thêm mô tả rõ ràng nhất về vấn đề "hiệu năng của query_posts ()": Sử dụng query_posts () hoặc WP_Query trong một tệp mẫu sẽ có cùng chi phí thực hiện: truy vấn bạn vừa thực hiện. Vấn đề được thảo luận trong bài viết về codex là nếu bạn thực sự muốn thay thế truy vấn, bạn nên làm như vậy bằng cách lọc truy vấn gốc_posts () bằng bộ lọc 'parse_query'. Bằng cách đó, bạn chỉ có một truy vấn duy nhất, ban đầu, mong muốn, thay vì truy vấn thứ hai để thay thế nó một cách vụng về. query_posts () KHÔNG BAO GIỜ LÀ CÁCH !! KHÔNG BAO GIỜ!
jerclarke

22
Có một lời giải thích tuyệt vời về query_posts được viết bởi John James Jacoby trên blog developer.wordpress.com, thổi bay tất cả những câu trả lời này ra khỏi nước. Điểm chính: query_postshoàn toàn không sửa đổi vòng lặp chính, nó sẽ thay thếsau khi nó đã chạy. Cách tốt nhất để sửa đổi vòng lặp chính là thông qua pre_get_postsbộ lọc. developer.wordpress.com/2012/05/14/NH
Dan Gayle

65

query_posts- Bạn không bao giờ nên sử dụng query_posts. Ngoài những gì @Rarst đã nói, vấn đề thực sự lớn query_postslà, nó phá vỡ đối tượng truy vấn chính (được lưu trữ trong $wp_query). Rất nhiều plugin và mã tùy chỉnh phụ thuộc vào đối tượng truy vấn chính, do đó, việc phá vỡ đối tượng truy vấn chính có nghĩa là bạn đang phá vỡ các chức năng của plugin và mã tùy chỉnh. Chỉ cần một chức năng như vậy là tất cả chức năng phân trang quan trọng, vì vậy nếu bạn phá vỡ truy vấn chính, bạn sẽ phá vỡ phân trang.

Để chứng minh mức độ xấu của query_postsnó, trên bất kỳ mẫu nào, hãy làm như sau và so sánh kết quả

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

get_postsWP_Querylà cách chính xác để xây dựng các truy vấn thứ cấp ( như các bài đăng liên quan, thanh trượt, nội dung nổi bật và nội dung trên các trang đầu tĩnh ) với. Cần lưu ý, bạn không nên sử dụng bất kỳ một trong hai ưu tiên cho truy vấn chính trên trang chủ, trang đơn hoặc bất kỳ loại trang lưu trữ nào vì nó sẽ phá vỡ chức năng của trang. Nếu bạn cần sửa đổi truy vấn chính, hãy sử dụng pre_get_postsđể làm như vậy và không phải là truy vấn tùy chỉnh. ( CẬP NHẬT: Đối với trang trước tĩnh và trang thật, hãy xem Sử dụng pre_get_posts trên trang thật và trang trước tĩnh *)

Về bản chất, WP_Queryđược sử dụng bởi truy vấn chính và cũng được sử dụng bởi get_posts, nhưng mặc dù get_posts()sử dụng WP_Query, có một vài khác biệt

  • get_postslà nhanh hơn WP_Query. Biên độ phụ thuộc vào số lượng tổng số bài viết của trang web. Lý do cho điều này là, get_postsđi 'no_found_rows' => truetheo mặc định để WP_Querymà bỏ qua / hợp pháp phá vỡ pagination. Với 'no_found_rows' => true, WP_Querynhận được số lượng bài đăng được truy vấn, sau đó giải cứu, theo mặc định, nó sẽ tìm kiếm thêm tất cả các bài đăng phù hợp với truy vấn để tính toán phân trang.

    Vì lý do này, get_posts()chỉ nên được sử dụng cho các truy vấn không phân trang. Pagination get_poststhực sự là một mớ hỗn độn lớn. WP_Querynên được sử dụng cho tất cả các truy vấn phân trang

  • get_posts()không bị ảnh hưởng bởi các posts_*bộ lọc WP_Querybị ảnh hưởng bởi các bộ lọc này. Lý do là get_posts, theo mặc định, chuyển 'suppress_filters' => trueđếnWP_Query

  • get_postscó một vài tham số bổ sung như include, exclude, numberpostscategory. Các tham số này được thay đổi thành các tham số hợp lệ cho WP_Querytrước khi được chuyển đến WP_Query. includeđược thay đổi thành post__in, excludethành post__not_in, categoryvào catnumberpostsvào posts_per_page. Chỉ cần một lưu ý, tất cả các tham số có thể được chuyển qua để WP_Querylàm việc với get_posts, bạn có thể bỏ qua và không sử dụng các tham số mặc định củaget_posts

  • get_postschỉ trả về thuộc $poststính WP_Querytrong khi WP_Querytrả về đối tượng hoàn chỉnh. Đối tượng này khá hữu ích khi nói đến điều kiện, phân trang và thông tin hữu ích khác có thể được sử dụng bên trong vòng lặp.

  • get_postskhông sử dụng vòng lặp, nhưng foreachvòng lặp để hiển thị bài viết. Ngoài ra, không có thẻ mẫu có sẵn theo mặc định. setup_postdata( $post )phải được sử dụng để làm cho các thẻ mẫu có sẵn. WP_Querysử dụng các thẻ vòng lặp và mẫu có sẵn theo mặc định

  • get_postsđi 'ignore_sticky_posts' => 1tới WP_Query, vì vậy get_poststheo mặc định bỏ qua bài viết dính

Dựa trên những điều trên, việc sử dụng get_postshay WP_Querytùy thuộc vào bạn và bạn thực sự cần gì từ truy vấn. Ở trên sẽ hướng dẫn bạn trong sự lựa chọn của bạn


1
Tôi ước tôi có thể yêu thích câu trả lời. Điều này giải thích rất nhiều.
Patrik Alienus

1
Giải thích tuyệt vời! "get_posts () chỉ nên được sử dụng cho các truy vấn không được phân trang. Việc hiển thị get_posts thực sự là một mớ hỗn độn lớn. WP_Query nên được sử dụng cho tất cả các truy vấn được phân trang"
Bullyen

32

Sự khác biệt cơ bản query_posts()là thực sự chỉ để sửa đổi Loop hiện tại. Khi bạn đã hoàn tất, cần phải thiết lập lại vòng lặp và gửi nó theo cách vui vẻ. Phương pháp này cũng dễ hiểu hơn một chút, đơn giản vì "truy vấn" của bạn về cơ bản là một chuỗi URL mà bạn chuyển đến hàm, như vậy:

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

Mặt khác, WP_Querylà một công cụ có mục đích chung hơn, và giống như trực tiếp viết các truy vấn MySQL hơn query_posts()là. Bạn cũng có thể sử dụng nó ở bất cứ đâu (không chỉ trong Vòng lặp) và nó không can thiệp vào bất kỳ truy vấn bài đang chạy nào.

Tôi có xu hướng sử dụng WP_Querythường xuyên hơn, như nó xảy ra. Thực sự, nó sẽ đi vào trường hợp cụ thể của bạn.


15

Đơn giản là không cần sử dụng query_posts(). Tất cả những gì nó làm là khởi tạo một đối tượng WP_Query mới và gán lại đối tượng mới đó global wp_query.

Để tham khảo, sau đây là query_posts()chức năng thực tế .

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

Khởi tạo đối tượng WP_Query của riêng bạn nếu bạn muốn tạo một tập lệnh truy vấn tùy chỉnh chuyên sâu. Hoặc sử dụng get_posts()nếu tất cả những gì bạn cần làm là một số thao tác nhẹ ở đây và đó.

Trong cả hai trường hợp, tôi đặc biệt khuyên bạn nên tự mình làm và tiếp tục wp_includes/query.phpvà tìm hiểu kỹ về WP_Querylớp học.


14

Đảm bảo rằng bạn sử dụng wp_reset_query()sau khi sử dụng query_posts()vì nó cũng sẽ ảnh hưởng đến kết quả truy vấn khác.


10

Nếu tôi nhớ đọc đúng, về cơ bản "vòng lặp" đang hoạt động WP_Querytrong các tệp cốt lõi, nhưng theo cách dễ hiểu hơn.


6
  • query_posts () : có thể được sử dụng trong một và chỉ một trường hợp nếu bạn cần sửa đổi truy vấn chính. Nó đặt rất nhiều biến toàn cục;
  • get_posts () : nó rất giống nhau về cơ học và chấp nhận các đối số tương tự, nhưng trả về mảng các bài đăng
  • WP_Query : bạn có thể tạo và làm việc với đối tượng riêng của nó. Bit phức tạp hơn, ít hạn chế hơn, nó an toàn để sử dụng ở bất cứ đâu.

-6

Tôi sẽ nói không sử dụng get_posts()trong một plugin. Nó áp đặt các bộ lọc rất hạn chế trong một số trường hợp (set của suppress_filters, ignore_sticky_posts, vv) và nên có lẽ chỉ được sử dụng trong một chủ đề khi bạn muốn một cái gì đó thực hiện nhanh chóng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.