Cách truy vấn bài viết trong WordPress

Truy vấn bài viết là khâu quan trọng trong khi bạn viết giao diện cho WordPress, nếu như bạn hiểu sai vấn đề thì bạn sẽ không lấy được bài viết theo như mong muốn của bạn. Không những viết giao diện mà ngay cả viết plugin cho WordPress thì bạn cũng cần phải nắm rõ về vấn đề này.

Lấy bài viết trong WordPress như thế nào

Theo như hình bên trên thì bạn thấy có 3 cách để chúng ta lấy bài viết từ cơ sở dữ liệu, tuy nhiên đối với những cách này thì bạn không nên dùng vì nó khá phức tạp và có khả năng xảy ra lỗi cho blog của bạn, đặc biệt là hàm query_posts.

Trong các phiên bản mới nhất của WordPress mới ra gần đây, bạn có thể sử dụng hook pre_get_posts để thay thế cho cách truy vấn bài viết được cho là lỗi thời của WordPress. Hook này sẽ thực hiện thay đổi truy vấn đến cơ sở dữ liệu trước khi câu lệnh lấy bài viết được thực thi.

1. query_posts

Đối với hàm này thì tuyệt đối Sáu khuyên bạn không nên sử dụng. Hàm này sẽ ảnh hưởng trực tiếp đến biến toàn cục $wp_query do vậy nếu bạn sử dụng nhiều lần thì kết quả tìm kiếm bài viết sẽ không chính xác.

Để dùng hàm này thì bạn phải dùng kèm theo hàm wp_reset_query để trả lại biến $wp_query cho các lệnh truy vấn khác.

 <?php
// The Query
query_posts( $args );

// The Loop
while ( have_posts() ) : the_post();
    echo '<li>';
    the_title();
    echo '</li>';
endwhile;

// Reset Query
wp_reset_query();
?> 

2. new WP_Query

Khi chúng ta khai báo một biến với giá trị là đối tượng WP_Query thì biến này sẽ sở hữu tất cả các thuộc tính bên trong của đối tượng. Bạn có thể sử dụng cách này để truy vấn bài viết khác nhau trong WordPress. Và bạn phải sử dụng kèm theo hàm wp_reset_postdata để trả lại giá trị ban đầu cho biến toàn cục $post. Cách sử dụng đơn giản nhất sẽ giống như đoạn code bên dưới:

<?php

// The Query
$the_query = new WP_Query( $args );

// The Loop
if ( $the_query->have_posts() ) {
        echo '<ul>';
	while ( $the_query->have_posts() ) {
		$the_query->the_post();
		echo '<li>' . get_the_title() . '</li>';
	}
        echo '</ul>';
} else {
	// no posts found
}
/* Restore original Post Data */
wp_reset_postdata(); ?>

3. get_posts

Đây là cách đơn giản và dễ dùng nhất trong 3 cách trên, get_posts có thể giúp bạn lấy bài viết theo ý thích của bạn. Cũng giống như cách 2, bạn phải sử dụng kèm theo hàm wp_reset_postdata phía sau vòng lặp để trả lại giá trị của biến $post toàn cục.

<?php
$args = array( 'posts_per_page' => 3 );
$lastposts = get_posts( $args );
foreach ( $lastposts as $post ) :
  setup_postdata( $post ); ?>
	<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
	<?php the_content(); ?>
<?php endforeach; 
wp_reset_postdata(); ?>

Như vậy, bạn có thể sử dụng cách 2 hoặc cách 3 để sử dụng vào giao diện cho việc truy vấn bài viết. Tuy nhiên, cách mới nhất và an toàn nhất vẫn là dùng hook pre_get_posts.

function my_home_category( $query ) {
    if ( $query->is_home() && $query->is_main_query() ) {
        $query->set( 'cat', '123' );
    }
}
add_action( 'pre_get_posts', 'my_home_category' );

Kết luận

Qua bài viết này Sáu hy vọng rằng bạn sẽ biết cách lấy bài viết trong khi viết giao diện hoặc plugin cho WordPress, có những thứ tưởng chừng như đơn giản nhưng bạn phải xem và nắm thật kỹ thì mới làm đúng được. Ngược lại, có những thứ bạn cảm thấy thật khó, bạn cứ nghĩ mình không thể làm được nhưng thật ra thì nó cũng không khó như bạn đang suy nghĩ. Chúc bạn thành công.

Gửi bình luận của bạn 21 bình luận

  1. Hi bạn, mình có 1 vấn đề với loop page. Mình có tạo và set static 2 page là :
    – Front page : Home
    -Posts page : Post
    Thì ở Page “Post” hiển thị đầy đủ post mới nhất và chuyển trang tiếp theo đc còn “Home” thì cũng hiển thị đầy đủ post mới nhưng ko chuyển trang đc . Thử đổi front page : “Post” và posts page : “Home” thì cũng chỉ có “Home” là chuyển trang đc , ” Post ” thì ko. Vậy cho mình hỏi có cách nào để fornt page có thể hiển thị đầy đủ new post và chuyển trang được ko ? tks

    • Chào bạn, để muốn hiểu thêm về truy vấn trong WordPress thì bạn phải đọc hiểu được cái hình bên trên.

      The most appropriate use for get_posts is to create an array of posts based on a set of parameters. It retrieves a list of recent posts or posts matching this criteria. get_posts can also be used to create Multiple Loops, though a more direct reference to WP_Query using new WP_Query is preferred in this case.

      The parameters of get_posts are similar to those of get_pages but are implemented quite differently, and should be used in appropriate scenarios. get_posts uses WP_Query, whereas get_pages queries the database more directly. Each have parameters that reflect this difference in implementation.

      Chỉ là không nên dùng query_posts vì nó làm thay đổi các biến toàn cục trong khi truy vấn. Còn WP_Query thì bạn có thể sử dụng để viết nhiều câu truy vấn trên cùng một trang, trong trường hợp bạn muốn tạo nhiều truy vấn thì WP_Query được khuyến khích sử dụng hơn get_posts nhé.

      Còn việc bạn lựa chọn dùng get_posts hay WP_Query đều được, không có gì được cho là nên hay không nên nhé.

  2. Cảm ơn anh về bài viết !. Em xin phép được hỏi cái này .
    Nếu viết theo cách mới nhất (‘Tuy nhiên, cách mới nhất và an toàn nhất vẫn là dùng hook pre_get_posts)
    thì giả sử là : trang home: có một list bài viết nổi bật, một list bài viết trong ngày, thì mình sẽ viết theo kiểu thứ ba như thế nào vậy anh.
    Em xin chân thành cảm ơn !

    • Chào bạn, nếu trên cùng một trang (ví dụ trang home) mà bạn muốn sử dụng nhiều câu truy vấn khác nhau cho các mục đích khác nhau thì bạn phải dùng truy vấn tùy chỉnh. Cái pre_get_posts chỉ phù hợp để chỉnh sửa các truy vấn đơn trên cùng một trang.

      Nếu trường hợp trong $args query của bạn có tham số bạn tự bỏ vào để nhận biết đâu là cái bạn cần thì bạn có thể dùng pre_get_posts trong trường hợp này.

      Ngược lại, nếu có quá nhiều query trên cùng 1 trang (nhiều hơn 1) thì bạn nên dùng new WP_Query.

  3. bạn ơi cho mình hỏi điều này nhá !
    Mình có danh mục video hiển thị khác với danh mục khác thì mình làm thêm file category-video.php , bây giờ mình có danh mục con của danh mục video hiển thị khác với danh mục video thì mình có cách làm bằng thêm file được không.
    hiện tại cách của mình là mình dùng if else để phân biệt đâu là danh mục cha , con của video

Gửi bình luận

Địa chỉ email của bạn sẽ được giữ bí mật. Những mục bắt buộc được đánh dấu *