---
description: >-
  https://thachpham.com/wordpress/wordpress-development/su-dung-wp-query-va-loop-vong-lap-de-lay-bai-viet.html
---

# plugin Debug Bar query check (ok)

## SỬ DỤNG WP QUERY VÀ LOOP (VÒNG LẶP) ĐỂ LẤY BÀI VIẾT

bởi [Thạch Phạm](https://thachpham.com/author/phamngocthach) 18 bình luận 11770 views[![](https://thachpham.com/wp-content/uploads/2020/12/nvme-hosting-768x90-1.png)](https://azdigi.com/ssd-hosting/nvme-hosting/)

https://www.youtube.com/watch?v=JMf9Eg4et04\&list=PLl4nkmb3a8w3qzoFaXLsPohofWUMTOHBU\&index=4

**Query** (_truy vấn_) là một thuật ngữ hay dùng nhất trong WordPress để chỉ các truy vấn gửi đến cơ sở dữ liệu (database) để lấy thông tin của Post (hoặc Page, hoặc bất cứ một cái gì). Nếu giải thích cặn kẽ về truy vấn thì rất là dài dòng, nhưng trong bài này bạn chỉ tạm hiểu rằng **truy vấn là một tập hợp các lệnh SQL gửi đến MySQL Server nhằm lấy dữ liệu của các bài viết trên WordPress**.

Trong bài viết này, mình sẽ hướng dẫn bạn đi tìm hiểu về các query mặc định trong WordPress ở mỗi trang, và cách tạo mới một query đến database thông qua class [WP\_Query](https://codex.wordpress.org/Class_Reference/WP_Query).

#### Cách query  ở mỗi trang <a href="#ftoc-heading-1" id="ftoc-heading-1"></a>

Mặc định mỗi trang trên WordPress đều có chứa query, ví dụ ở trang chủ nó sẽ gửi query để lấy danh sách bài viết mới nhất, khi vào trang nội dung bài viết thì nó sẽ gửi query để lấy thông tin của bài viết đó dựa vào ID của bài viết (ở phần trước mình đã có nói là WordPress có thể phân tích truy vấn ở một trang dựa vào đường dẫn truy cập).

Nhưng để xem chính xác trên trang của bạn có bao nhiêu query, và nó gửi như thế nào thì chúng ta phải debug mới thấy được. Cách đơn giản nhất là bạn hãy [cài plugin](https://thachpham.com/wordpress/wordpress-tutorials/tim-va-cai-plugin.html) [Debug Bar](https://wordpress.org/plugins/debug-bar/) rồi chèn đoạn này vào _wp-config.php_:

| 01 | `define(` `'SAVEQUERIES', true );` |
| -- | ---------------------------------- |

Sau đó bạn ra trang chủ, ấn vào nút Debug trên Admin Bar và xem ở phần WP Query.[![Xem query của trang với Debug Bar](https://thachpham.com/wp-content/uploads/2015/07/debug-wpquery.jpg)](https://thachpham.com/wp-content/uploads/2015/07/debug-wpquery.jpg)

Xem query của trang với Debug Bar

Trong đó, phần ở trên là những thông tin quan trọng về query của trang hiện tại như template đang thực thi query (các tập tin trong theme), loại query. Còn phần _Query SQL_ là lệnh SQL thực thi query đó. Nếu bạn đã từng làm việc với SQL thì chắc chắn sẽ hiểu đoạn đó có nghĩa là gì. Như trong hình thì nó lấy dữ liệu trong bảng wp\_posts, số thứ tự là 1 và cột post\_type là post và post\_status  là publish và sắp xếp dựa theo giá trị cột post\_date theo thứ tự tăng dần với số lượng 10 đối tượng.  Nhưng mấy cái này bạn đừng lo vì WordPress có hỗ trợ chúng ta tạo query nhanh nhất mà không cần phải nhớ tên bảng, tên cột gì hết.

Tương tự, bạn có thể vào các trang khác rồi xem query của nó.

#### Kết quả của query lưu vào đâu? <a href="#ftoc-heading-2" id="ftoc-heading-2"></a>

Sau khi gửi query, thì chắc chắn phải có kết quả trả về của query đó. Ví dụ khi nó gửi query để lấy bài mới thì chắc chắn nó sẽ trả về các thông tin của bài mới mà query đó đang cần tìm. Và các kết quả của query sẽ được lưu vào đối tượng `$wp_query`.

Bây giờ, bạn hãy thử lookup cái đối tượng $wp\_query bằng cách chèn đoạn code dưới đây vào cuối template _footer.php_ trong theme:

| 0102030405 | `<?php    echo` `'<pre>';    print_r ($wp_query);    echo` `'</pre>';?>` |
| ---------- | ------------------------------------------------------------------------ |

Và bây giờ, bạn có thể đi qua các bài viết hoặc các trang nào đó để xem thông tin của đối tượng `$wp_query` sau khi nó đã gửi query, nó sẽ bao gồm tất cả các thông tin mà nó nhận được (trường hợp nó để trống là không có).

Tuy nhiên, các bạn lưu ý nhất cho mình ở chỗ thuộc tính `posts`.

[![wp-query-postobject](https://thachpham.com/wp-content/uploads/2015/07/wp-query-postobject.jpg)](https://thachpham.com/wp-content/uploads/2015/07/wp-query-postobject.jpg)

Và nếu bây giờ bạn chỉ cần xem dữ liệu của thuộc tính posts thì sửa lại code debug trỏ đến thuộc tính `posts` trong đối tượng `$wp_query.`

| 0102030405 | `<?php    echo` `'<pre>';    print_r ($wp_query->posts);    echo` `'</pre>';?>` |
| ---------- | ------------------------------------------------------------------------------- |

Nhưng đáng mừng cho bạn, là cái `$wp_query->posts` có một đối tượng riêng tên là `$posts`, nên có thể bạn chỉ cần lookup cái đối tượng `$posts` là ra.

| 0102030405 | `<?php    echo` `'<pre>';    print_r ($posts);    echo` `'</pre>';?>` |
| ---------- | --------------------------------------------------------------------- |

Và như bạn thấy, chúng ta đã có thể xem được các thuộc tính trong đối tượng `$posts` là các thông tin về bài viết.[![Các thuộc tính trong đối tượng $posts](https://thachpham.com/wp-content/uploads/2015/07/postsobject-propeties.jpg)](https://thachpham.com/wp-content/uploads/2015/07/postsobject-propeties.jpg)

Các thuộc tính trong đối tượng $posts

Tuy nhiên nếu bạn cần lấy ra, chúng ta nên lấy bằng đối tượng `$post` (không có chữ s ở cuối). Bây giờ bạn thử mở lại template _footer.php_, thử lookup cái thuộc tính `post_content` trong đối tượng `$post` xem sao nhé. Hoặc bạn có thể đặt nó ở một template bất kỳ trong theme, vào vị trí bất kỳ.

| 0102030405 | `<?php    echo` `'<pre>';    print_r ($post->post_content);    echo` `'</pre>';?>` |
| ---------- | ---------------------------------------------------------------------------------- |

#### Sử dụng vòng lặp (loop) cho query <a href="#ftoc-heading-3" id="ftoc-heading-3"></a>

Và nếu bạn làm đúng khi in `$post->post_content` thì nó sẽ trả về nội dung của bài viết hiện tại nếu bạn vào xem nội dung một post. Nhưng nếu bạn xem ngoài trang index, hay các trang lưu trữ như tag, category,…thì nó chỉ hiển thị nội dung bài viết đầu tiên. Tại sao?

Bởi vì cái $post thực chất là một đối tượng trong một mảng (array), nên nếu gọi như thế thì PHP sẽ tự hiểu chúng ta chỉ muốn gọi đối tượng đầu tiên trong mảng nên khi xem ở các trang có nhiều bài viết thì nó cũng chỉ hiển thị có một bài. Và để cho nó hiển thị toàn bộ, chúng ta **phải tạo vòng lặp** (loop) cho cái mảng đối tượng đó để nó lấy ra nhiều bài viết. Và chúng ta sẽ lặp thông qua phương thức `have_posts()` trong đối tượng `$wp_query`.

Trước khi tìm hiểu sâu xa, chúng ta hãy tìm hiểu cấu trúc của một đoạn vòng lặp trong WordPress, và cấu trúc của nó như sau:

| 01020304050607080910111213 | `<?php    if(` `$wp_query->have_posts() ) {` `// Nếu phương thức have_posts() trả về TRUE thì mới chạy code bên trong        while(` `$wp_query->have_posts() ) {` `// Nếu have_posts() == TRUE thì nó mới lặp, không thì ngừng            $wp_query->the_post();` `// Thiết lập số thứ tự bài viết trong chỉ mục của query` `/*` `* Nội dung hiển thị bài viết` `*/            echo` `$post->post_title .` `'<br>';` `}    }?>` |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

Mình viết vậy cho các bạn dễ hiểu chứ thường thì WordPress nó hay viết ngắn gọn thành như thế này:

| 01020304050607080910 | `<?php    if(` `$wp_query->have_posts() ) :` `while(` `$wp_query->have_posts() ) :` `$wp_query->the_post();` `/*` `* Nội dung hiển thị bài viết` `*/            echo` `$post->post_title .` `'<br>';` `endwhile;` `endif;?>` |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

Bạn đặt cái này vào vị trí nào đó trong template như ở footer.php chẳng hạn, rồi ra ngoài trang chủ hoặc trang lưu trữ xem là bạn sẽ thấy nó gọi ra tiêu đề bài viết của nhiều bài khác nhau.

Ý nghĩa ra sao thì mời bạn đọc comment và xem thêm chi tiết các phương thức bên dưới.

**Ý nghĩa phương thức have\_posts()**

Phương thức `have_posts()` là một phương thức của class `WP_Query` vốn tạo ra đối tượng `$wp_query`. Phương thức này được khai báo trong tập tin _/wp-includes/query.php_ tại dòng 3739 – 3767.

| 0102030405060708091011121314151617181920212223242526272829 |     `/**` `* Whether there are more posts available in the loop.` `*` `* Calls action 'loop_end', when the loop is complete.` `*` `* @since 1.5.0` `* @access public` `*` `* @return bool True if posts are available, false if end of loop.` `*/    public` `function` `have_posts() {        if` `(` `$this->current_post + 1 <` `$this->post_count ) {            return` `true;        }` `elseif` `(` `$this->current_post + 1 ==` `$this->post_count &&` `$this->post_count > 0 ) {            /**` `* Fires once the loop has ended.` `*` `* @since 2.0.0` `*` `* @param WP_Query &$this The WP_Query instance (passed by reference).` `*/            do_action_ref_array(` `'loop_end',` `array( &$this` `) );            // Do some cleaning up after the loop            $this->rewind_posts();        }` `$this->in_the_loop = false;        return` `false;    }` |
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

Ý nghĩa của phương thức này rất đơn giản, đó là nó sẽ **kiểm tra xem còn bài viết nào trong query hay không**. Sở dĩ nó có thể kiểm tra được là nó lấy số thứ tự của bài viết hiện tại (thuộc tính `current_post`) cộng thêm 1 đơn vị mà nhỏ hơn tổng số bài viết trong query (thuộc tính `post_count`) thì nó sẽ trả kết quả về là true. Ngược lại là FALSE.

Và đoạn này:

| 01 | `if(` `$wp_query->have_posts() )` |
| -- | --------------------------------- |

nghĩa là nó kiểm tra xem nếu nó có bài viết trong query hiện tại ($wp\_query) thì nó sẽ thực hiện vòng lặp bên dưới.

| 01 | `while(` `$wp_query->have_posts() )` |
| -- | ------------------------------------ |

Và trong vòng lặp này, nó sẽ lặp nếu thằng have\_posts() trả về kết quả là true. Còn false thì nó sẽ dừng.

**Phương thức the\_post()**

Sau khi gọi vòng lặp ra, các bạn có thể thấy nó có thêm phương thức `the_post()` bên trong. Vậy cái này là gì?

Phương thức này được khai báo ở _/wp-includes/query.php_ tại dòng 3712 – 3737.

| 0102030405060708091011121314151617181920212223242526 |     `/**` `* Sets up the current post.` `*` `* Retrieves the next post, sets up the post, sets the 'in the loop'` `* property to true.` `*` `* @since 1.5.0` `* @access public` `*/    public` `function` `the_post() {        global` `$post;        $this->in_the_loop = true;` `if` `(` `$this->current_post == -1 )` `// loop has just started            /**` `* Fires once the loop is started.` `*` `* @since 2.0.0` `*` `* @param WP_Query &$this The WP_Query instance (passed by reference).` `*/            do_action_ref_array(` `'loop_start',` `array( &$this` `) );` `$post` `=` `$this->next_post();        $this->setup_postdata(` `$post` `);    }` |
| ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

Phương thức này nghĩa là nó sẽ đánh chỉ mục thứ tự cho bài viết trong vòng lặp và chức năng cụ thể là sẽ thiết lập thuộc tính in\_the\_loop sang true vì mặc định là false, mà nếu nó là true thì phương thức next\_post() có thể thực thi nhằm lấy bài viết tiếp theo.

Vậy kết luận, phương thức này sẽ có chức năng **đếm chỉ mục để gọi bài kế tiếp trong vòng lặp**, nếu bạn không khai báo phương thức này trong vòng lặp thì bài viết đầu tiên sẽ bị lặp đi lặp lại hoài mà không có điểm dừng.

**$wp\_query không cần khai báo trong vòng lặp**

$wp\_query là đối tượng chứa query mặc định trong trang, nên bạn có thể không cần gọi ra trong vòng lặp mà nó sẽ tự hiểu là bạn đang lặp query mặc định.

| 01020304050607080910 | `<?php    if( have_posts() ) :` `while( have_posts() ) : the_post();` `/*` `* Nội dung hiển thị bài viết` `*/            echo` `$post->post_title .` `'<br>';` `endwhile;` `endif;?>` |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

**Sử dụng template tags trong vòng lặp**

Trong vòng lặp, nếu bạn cần lấy thông tin bài viết ra thì có thể không cần dùng đến đối tượng $post, mà chỉ cần khai báo các hàm [template tag](https://codex.wordpress.org/Template_Tags) (xem bài trước) mà thôi. Nó sẽ tự hiểu bạn lấy đối tượng trong query mà nó đang lặp (xem nội dung file _/wp-includes/post-template.php_ để biết thêm chi tiết).

| 01020304050607080910 | `<?php    if( have_posts() ) :` `while( have_posts() ) : the_post();` `/*` `* Nội dung hiển thị bài viết` `*/            the_title();` `endwhile;` `endif;?>` |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |

Ví dụ một đoạn vòng lặp hoàn chỉnh

Bằng cách kết hợp với HTML, chúng ta có thể tạo ra một vòng lặp để lấy danh sách bài viết như thế này:

| 0102030405060708091011121314151617 | `<?php    if( have_posts() ) :` `while` `( have_posts() ) : the_post();?> <!--Đóng PHP để viết HTML tiện hơn ở dưới-->` `<!--Nội dung một bài viết-->    <article <?php post_class() ?> >        <h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>        <summary>            <?php the_content(); ?>        </summary>        <footer>            <?php the_tags(); ?>        </footer>    </article>    <!--kết thúc nội dung-->` `<?php` `endwhile;` `endif;` `// Kết thúc vòng lặp ?>` |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

Sẵn đây mình nói luôn, các thẻ kiểu `<article>`,`<summary>`,`<footer>` cũng giống thẻ `<div>` thôi, đó là các thẻ HTML5 nên nhìn có cấu trúc hơn.

#### Tạo một đối tượng query mới với WP\_Query <a href="#ftoc-heading-8" id="ftoc-heading-8"></a>

Sau khi xem phần trên thì bạn đã biết WordPress có một truy vấn mặc định trên mỗi trang được lưu trong đối tượng $wp\_query. Nhưng đáng mừng thay, bạn có thể tạo ra nhiều đối tượng query khác với các tham số tuỳ chỉnh lấy bài viết theo ý bạn muốn, đó là chúng ta sẽ sử dụng class WP\_Query.

**Cách sử dụng**

Cách sử dụng class này khá đơn giản, đó là tạo mới nó vào một biến làm đối tượng và khai báo các tham số (dạng mảng) để tuỳ chỉnh lấy bài viết.

| 01 | `$my_query` `=` `new` `WP_Query(` `$args` `);` |
| -- | ---------------------------------------------- |

Trong đó, `$args` là biến chứa tham số. Ví dụ mình có thể khai báo tham số và tạo query thế này:

| 01020304050607 | `<?php$args_my_query` `=` `array(    'post_type'`    `=>    'post',    'orderby'`    `=>` `'rand');$my_query` `=` `new` `WP_Query(` `$args_my_query` `);?>` |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |

Rồi sau đó, bạn mang cái đối tượng `$my_query` bỏ vào vòng lặp là được.

| 01020304050607080910 | `<?php    if(` `$my_query->have_posts() ) :` `while(` `$my_query->have_posts() ) :` `$my_query->the_post();` `/*` `* Nội dung hiển thị bài viết` `*/            the_title();` `endwhile;` `endif;?>` |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

Ở đây mình sẽ không nói đến việc tạo một query mới kèm theo phân trang mà mình sẽ nói vấn đề này ở một bài viết riêng.

**Danh sách các tham số của WP\_Query**

Sức mạnh của WP\_Query là nằm ở các tham số. Với số lượng tham số đa dạng và phong phú, bạn có thể lấy bất cứ kiểu bài viết nào trong bất kỳ chỗ nào trên website. Các tham số mình đã gom lại thành một ghi chú, bạn có thể tham khảo tại[ https://gist.github.com/thachpham92/d57b18cf02e3550acdb5.](https://gist.github.com/thachpham92/d57b18cf02e3550acdb5)

#### Lời kết <a href="#ftoc-heading-11" id="ftoc-heading-11"></a>

Bài viết này có lẽ hơi dài, nhưng đó là những gì quan trọng nhất về WP Query mà mình muốn nhắn đến bạn. Bằng việc nắm vững cách sử dụng WP Query và hiểu query trong WordPress, bạn có thể làm được rất nhiều việc vì hầu như trong WordPress chúng ta sử dụng WP Query rất nhiều.\
