Bootstrap Skip to main content
Use code LAMVT for an extra 10% off!

From the Firehose

5/5 - (2 bình chọn)

Câu hỏi

Hôm qua tôi đã đọc bài You don’t know Query của @nacin’s và tôi cảm thấy bị loạn. Trước đó, tôi luôn dùng query_posts () bất cứ khi nào tôi cần dùng đến truy vấn, và bây giờ tôi đã biết đó là một cách làm sai. Giờ tôi đã biết rõ hơn một chút về cách dùng WP_Query (), nhưng vẫn còn một số vấn đề vướng mắc.

Khi nào thì dùng WP_Query (), query_posts () và pre_get_posts how-to-use-the-wp_query-function

Tôi nghĩ là tôi đã nắm rõ những điều sau đây:

Nếu tôi tạo vòng lặp bổ sung vào đâu đó trong một trang web – trong thanh bên (sidebar), ở chân trang, với bất kì các bài viết liên quan, ví dụ như vậy, tôi sẽ cần sử dụng WP_Query (). Tôi có thể sử dụng nó nhiều lần trong một trang mà không sợ có ảnh hưởng xấu gì. (Tôi hiểu như vậy có đúng không?)

Những điểm mà tôi chưa chắc chắn:

  1. Khi nào thì nên dùng pre_get_posts, khi nào thì dùng WP_Query (), @nacin’s? Tôi có nên sử dụng pre_get_posts cho mọi thứ không?
  2. Khi tôi muốn chỉnh sửa vòng lặp trong một trang mẫu – hay nói cách khác là tôi muốn chỉnh sửa một trang lưu trữ phân loại – thì tôi có cần phải bỏ đi phần if have_posts : while have_posts : the_post và viết WP_Query () của riêng mình không? Hay là tôi cần sửa đổi đầu ra bằng cách sử dụng pre_get_posts trong tệp functions.php của tôi?

tl;dr

Các quy tắc tl; dr tôi muốn rút ra từ đây là:

  1. Đừng bao giờ sử dụng query_posts.
  2. Khi chạy nhiều truy vấn trên một trang, hãy sử dụng WP_Query ()
  3. Khi sửa đổi một vòng lặp, hãy thực hiện điều này __________________.

Cảm ơn vì những lời khuyên rất thông minh.

Terry

Tái bút: Tôi đã nhìn thấy và đọc bài: When should you use WP_Query vs query_posts() vs get_posts()? Ở đó có nói đến một hướng khác là get_posts, nhưng không đề cập đến pre_get_posts.

saltcod

Có thể là bản sao của When should you use WP_Query vs query_posts() vs get_posts()? – dotancohen Jan 3 ’16 at 10:29

@saltcod, bây giờ đã khác rồi, WordPress đã được cải tiến hơn, tôi thêm một vài bình luận để so sánh với câu trả lời có thể chấp nhận được ở đây. – prosti Dec 28 ’16 at 1:46

Câu trả lời chính xác nhất

Tôi đồng ý với bạn rằng là:

Đừng bao giờ sử dụng query_posts.

pre_get_posts

pre_get_posts là một bộ lọc dùng để thay đổi bất kì truy vấn nào. Nó thường được sử dụng chỉ để thay đổi ‘truy vấn chính’:

add_action(‘pre_get_posts’,’wpse50761_alter_query’);
function wpse50761_alter_query($query){

if( $query->is_main_query() ){
//Do something to main query
}
}

(Tôi cũng sẽ kiểm tra xem is_admin () trả về false – mặc dù điều này có vẻ thừa thãi). Truy vấn chính xuất hiện trong các mẫu của bạn như là:

if( have_posts() ):
while( have_posts() ): the_post();
//The loop
endwhile;
endif;

Nếu bạn cảm thấy cần thiết chỉnh sửa lại vòng lặp này thì hãy sử dụng pre_get_posts. Ví dụ, nếu bạn đang có thói quen sử dụng query_posts () thì hãy dùng pre_get_posts để thay thế.

WP_Query 

Truy vấn chính (main query) là một ví dụ điển hình cho một đối tượng của WP_Query. Một ví dụ là WordPress sử dụng nó để quyết định xem phải sử dụng mẫu nào, và bất kỳ đối số nào được chuyển vào url (ví dụ: sự phân trang – pagination) đều được chuyển vào trường hợp đó của đối tượng WP_Query.

Đối với vòng lặp thứ cấp (ví dụ như trong thanh bên hoặc danh sách các bài viết liên quan) bạn sẽ muốn tạo một trường hợp riêng cho đối tượng WP_Query. Ví dụ:

$my_secondary_loop = new WP_Query(…);
if( $my_secondary_loop->have_posts() ):
while( $my_secondary_loop->have_posts() ): $my_secondary_loop->the_post();
//The secondary loop
endwhile;
endif;
wp_reset_postdata();

Hãy chú ý wp_reset_postdata (), bởi vì vòng lặp thứ cấp sẽ ghi đè lên biến $ post toàn cục, xác định ‘bài đăng hiện tại’. Về cơ bản, điều này đặt lại cho $ post chúng ta đang sử dụng.

get_posts()

Đây thực chất là một trình bao bọc cho một cá thể riêng biệt của một đối tượng WP_Query. Nó trả về một mảng các đối tượng bài viết. Các phương pháp được sử dụng trong vòng lặp ở trên không còn có sẵn cho bạn nữa. Đây không phải là một ‘Loop’, chỉ đơn giản là một mảng của đối tượng bài viết.

<ul>
<?php
global $post;
$args = array( ‘numberposts’ => 5, ‘offset’=> 1, ‘category’ => 1 );
$myposts = get_posts( $args );
foreach( $myposts as $post ) : setup_postdata($post); ?>
<li><a href=”<?php the_permalink(); ?>”><?php the_title(); ?></a></li>
<?php endforeach; wp_reset_postdata(); ?>
</ul>

Đáp lại các câu hỏi của bạn

  1. Sử dụng pre_get_posts để thay đổi truy vấn chính của bạn. Sử dụng một đối tượng WP_Query riêng biệt (phương thức 2) cho các vòng thứ cấp trong các trang mẫu.
  2. Nếu bạn muốn thay đổi truy vấn của vòng lặp chính, hãy sử dụng pre_get_posts.

Trả lời bởi Stephen Harris

Có trường hợp nào chỉ cần dùng get_posts() mà không phải là WP_Query không? – urok93 Aug 25 ’12 at 16:09

@drtanz – Có chứ, ví dụ như khi bạn không cần đánh số trang hoặc đính bài viết ở đầu. Trong những trường hợp như vậy thì get_posts() sẽ hiệu quả hơn. – Stephen Harris Aug 25 ’12 at 18:00

Nhưng làm vậy sẽ không thêm một truy vấn phụ khi chúng ta chỉ có thể sửa đổi pre_get_posts để sửa đổi truy vấn chính chứ? – urok93 Aug 26 ’12 at 20:54

@drtanz – Bạn đừng dùng get_posts() cho truy vấn chính, nó được sử dụng cho truy vấn phụ. – Stephen Harris Aug 26 ’12 at 22:42

@StephenHarris – Đúng vậy, nếu bạn dùng next_post() cho đối tượng thay vì the_post, bạn sẽ không phải làm việc với truy vấn toàn cục (global query) và sau đó không cần phải nhớ sử dụng wp_reset_postdata. – Privateer Sep 19 ’15 at 18:01

 

About

Chào bạn, mình là Vũ Thành Lâm.
Tri Thức là Sức Mạnh, Tri thức không của riêng ai, hãy chia sẻ nó!

Recent posts