Bird
Raised Fist0
Wordpressframework~10 mins

WP_Query class in Wordpress - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - WP_Query class
Create WP_Query object with args
↓
WP_Query runs SQL query
↓
Fetch posts matching criteria
↓
Store posts in object property
↓
Use loop: have_posts() and the_post()
↓
Output post data
↓
Reset post data after loop
This flow shows how WP_Query creates a query, fetches posts, and lets you loop through them.
Execution Sample
Wordpress
<?php
$query = new WP_Query(['category_name' => 'news', 'posts_per_page' => 2]);
if ($query->have_posts()) {
  while ($query->have_posts()) {
    $query->the_post();
    the_title();
  }
}
wp_reset_postdata();
This code queries 2 posts from the 'news' category and outputs their titles.
Execution Table
StepActionEvaluationResult
1Create WP_Query with argscategory_name='news', posts_per_page=2WP_Query object with query prepared
2Call have_posts()Check if posts existTrue (posts found)
3Call the_post()Set current post to first postCurrent post set to post 0
4Call the_title()Output post 0 titleTitle of post 0 displayed
5Call have_posts()Check if more postsTrue (post 1 exists)
6Call the_post()Set current post to second postCurrent post set to post 1
7Call the_title()Output post 1 titleTitle of post 1 displayed
8Call have_posts()Check if more postsFalse (no more posts)
9Exit loopNo more postsLoop ends
10Call wp_reset_postdata()Reset global post dataGlobal post restored
💡 Loop ends when have_posts() returns false, meaning no more posts to show.
Variable Tracker
VariableStartAfter Step 3After Step 6Final
$query->current_post-1011
$query->posts[][post0, post1][post0, post1][post0, post1]
$post (global)original postpost0post1original post
Key Moments - 3 Insights
Why does have_posts() return true before the loop starts?
Because WP_Query fetches posts on creation, have_posts() checks if there are posts left to show. See execution_table rows 2 and 5.
What does the_post() do inside the loop?
the_post() moves the internal pointer to the next post and sets global $post. See execution_table rows 3 and 6.
Why call wp_reset_postdata() after the loop?
It restores the original global $post so other parts of the page work correctly. See execution_table row 10.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what is the value of $query->current_post after step 6?
A1
B0
C-1
D2
💡 Hint
Check variable_tracker row for $query->current_post after step 6.
At which step does have_posts() return false, ending the loop?
AStep 7
BStep 9
CStep 8
DStep 10
💡 Hint
See execution_table row where have_posts() returns false.
If posts_per_page was set to 1, how would the execution table change?
ALoop would run twice as usual
BLoop would run only once, steps 5-7 would be skipped
Chave_posts() would always return false
Dthe_post() would not set current post
💡 Hint
Look at how posts_per_page limits posts and affects loop iterations.
Concept Snapshot
WP_Query class lets you fetch posts with custom criteria.
Create with args array, then use have_posts() and the_post() to loop.
Inside loop, use template tags like the_title() to show data.
Always call wp_reset_postdata() after to restore global post.
It works like a custom post fetcher for WordPress themes and plugins.
Full Transcript
WP_Query is a WordPress class to get posts based on filters like category or number. You create a WP_Query object with arguments. It runs a database query and stores matching posts. Then you use have_posts() to check if posts exist and the_post() to move through them one by one. Inside the loop, you can output post info like titles. After the loop, call wp_reset_postdata() to reset global post data. This process helps you show custom lists of posts on your site.

Practice

(1/5)
1. What is the primary purpose of the WP_Query class in WordPress?
easy
A. To style posts with CSS classes
B. To create new posts in the WordPress admin
C. To fetch posts from the database based on custom criteria
D. To manage user roles and permissions

Solution

  1. Step 1: Understand WP_Query's role

    WP_Query is designed to retrieve posts from the database using filters like category, author, or date.
  2. Step 2: Differentiate from other WordPress features

    Creating posts, styling, or managing users are handled by other parts of WordPress, not WP_Query.
  3. Final Answer:

    To fetch posts from the database based on custom criteria -> Option C
  4. Quick Check:

    WP_Query fetches posts = A [OK]
Hint: WP_Query is for getting posts, not creating or styling [OK]
Common Mistakes:
  • Confusing WP_Query with post creation functions
  • Thinking WP_Query styles posts
  • Assuming WP_Query manages users
2. Which of the following is the correct way to start a new WP_Query to get posts from category ID 5?
easy
A. $query = WP_Query(array('cat' => 5));
B. $query = new WP_Query(array('cat' => 5));
C. $query = new WP_Query('category_id' => 5);
D. $query = WP_Query('category' => 5);

Solution

  1. Step 1: Check WP_Query instantiation syntax

    WP_Query must be created with the new keyword and an array of arguments.
  2. Step 2: Verify correct argument key for category

    The correct key for category ID is 'cat', not 'category' or 'category_id'.
  3. Final Answer:

    $query = new WP_Query(array('cat' => 5)); -> Option B
  4. Quick Check:

    Use new WP_Query with array('cat' => 5) = D [OK]
Hint: Use new WP_Query with array and 'cat' key for category ID [OK]
Common Mistakes:
  • Omitting the new keyword
  • Using wrong argument keys like 'category' or 'category_id'
  • Passing arguments without array
3. Given the following code, what will be the output if there are 3 posts in category 10?
$query = new WP_Query(['cat' => 10]);
if ($query->have_posts()) {
  while ($query->have_posts()) {
    $query->the_post();
    echo get_the_title() . ', ';
  }
} else {
  echo 'No posts found';
}
wp_reset_postdata();
medium
A. Titles of the 3 posts separated by commas
B. No posts found
C. Syntax error due to missing semicolons
D. Only the first post title printed

Solution

  1. Step 1: Understand the loop behavior

    The loop runs while have_posts() returns true, printing each post title followed by a comma.
  2. Step 2: Check the number of posts in category 10

    Since there are 3 posts, all 3 titles will be printed separated by commas.
  3. Final Answer:

    Titles of the 3 posts separated by commas -> Option A
  4. Quick Check:

    Loop prints all post titles = C [OK]
Hint: Loop prints all posts if have_posts() is true [OK]
Common Mistakes:
  • Thinking only one post prints
  • Assuming 'No posts found' when posts exist
  • Confusing syntax errors with correct code
4. What is wrong with this WP_Query usage?
$query = new WP_Query(['post_type' => 'product']);
while ($query->have_posts()) {
  the_post();
  echo get_the_title();
}
wp_reset_postdata();
medium
A. Incorrect post_type value
B. Using echo instead of print
C. Missing wp_reset_query() after the loop
D. Missing call to $query->the_post() inside the loop

Solution

  1. Step 1: Check loop method calls

    The loop uses $query->have_posts() but calls the_post() without the query object, which is incorrect.
  2. Step 2: Identify correct method usage

    Inside the loop, it should call $query->the_post() to set up post data properly.
  3. Final Answer:

    Missing call to $query->the_post() inside the loop -> Option D
  4. Quick Check:

    Use $query->the_post() in custom loops = B [OK]
Hint: Use $query->the_post() inside loop, not just the_post() [OK]
Common Mistakes:
  • Calling the_post() without query object in custom loops
  • Confusing wp_reset_postdata() with wp_reset_query()
  • Assuming echo vs print matters here
5. You want to display the latest 5 posts from category 3 but exclude posts tagged with 'featured'. Which WP_Query argument array correctly achieves this?
hard
A. ['cat' => 3, 'posts_per_page' => 5, 'tag__not_in' => [get_term_by('slug', 'featured', 'post_tag')->term_id]]
B. ['category_name' => '3', 'posts_per_page' => 5, 'tag__not_in' => ['featured']]
C. ['cat' => 3, 'posts_per_page' => 5, 'tag__not_in' => ['featured']]
D. ['cat' => 3, 'posts_per_page' => 5, 'tag__not_in' => get_term_by('slug', 'featured', 'post_tag')->term_id]

Solution

  1. Step 1: Identify correct category argument

    Use 'cat' => 3 to filter by category ID 3, not 'category_name' with a number string.
  2. Step 2: Exclude posts by tag ID

    The tag__not_in argument expects an array of tag IDs, so we must get the ID using get_term_by().
  3. Step 3: Check syntax for excluding 'featured' tag

    Using get_term_by('slug', 'featured', 'post_tag')->term_id inside the array correctly fetches the tag ID to exclude.
  4. Final Answer:

    ['cat' => 3, 'posts_per_page' => 5, 'tag__not_in' => [get_term_by('slug', 'featured', 'post_tag')->term_id]] -> Option A
  5. Quick Check:

    Use tag IDs with tag__not_in, not slugs = A [OK]
Hint: Exclude tags by ID array with tag__not_in, not by slug string [OK]
Common Mistakes:
  • Using tag slugs instead of tag IDs in tag__not_in
  • Using category_name with numeric ID
  • Not wrapping tag IDs in an array
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard