Custom WordPress Queries

At the bottom of my individual posts in Thesis Tips, I used to have a list of all my Thesis Tips This just checks to see if the current post is tagged ‘thesis-tip’, and that it’s not on the homepage, and if it meets those criteria then it lists all Thesis Tips.

I use this technique for lots of things. It can show the most recent posts in the footer, list of certain posts on specific pages… any time you want to call WordPress and not mess with the main content (called “The Loop”).

The Query

For information on all the parameters you can use, see WP_Query in the Codex.

For my example, I’m going to get all the posts tagged ‘thesis-tip’ and put them in a list with just the title hyperlinked to the post itself.

Make sure you include the wp_reset_postdata(), which will reset the global $post variable back to the default. If you don’t do this, WordPress will think the current page is whatever last item was in your new query, which will cause lots of issues (ex: comments from the wrong post showing up).

Tutorial

Receive New Posts by Email

Comments

  1. There is a spelling mistake in the line “if( $tips->hvae_posts() ):”

    “have”, instead of “hvae”!
    Just in case some will copy/paste the code. 😉

    1. Good catch. I’ve updated the code, so once my cache refreshes the change will be visible. Thanks!

  2. Hya,

    This is great, really helping me understand best practices for custom queries. Quick question and maybe kinda random: what the purpose of defining ‘posts_per_page’ => ‘-1’? I’ve tried to find answers on the forums, but can’t find an explanation. Why -1?

    thanks!

    1. -1 simply means “return all posts”. It indicates no limit on the number of posts per page. You could set an arbitrarily high number, like 9999, but -1 will always return all, so that’s why it’s the best practice.

  3. Is there a way to query the posts, dynamically? for instance, in your arguments where you have:

    ‘tag’ => ‘thesis-tip’,

    What if you don’t know what your ‘tag’/’term’/whatever is set to because the page is generated dynamically, for instance on a template page which could fall under any number of tags, categories or taxonomies?

    This is where I am stuck: I want my query to pull posts related to the one currently shown by its taxonomy term, but I don’t know what the term is beforehand because the template my function is used for could be outputting any number of the custom post types in my theme that fall under several different taxonomy terms.

    1. You can easily do this, in the main query in your template, store the value or id of the category/tag in a variable, the just send the variable into the tag key in the array

  4. Just wanted to state that this article saved my life. I have a decent grasp of custom queries, but I was trying to figure out how to set up custom loops like this. The code worked perfectly.

    Then, using this code, I found a way to run the loop multiple for each item in an array. Names of headers and classes and so on change dynamically based on array info.

    The next step is to figure out how to read data from custom taxonomies. Thanks for this and all your tutorials, Bill!

    Here is the code, for anyone who is curious. It contains a sample array, but I’ll soon replace it with a dynamic array based on the custom taxonomy meta. This code is in ‘home.php’: https://gist.github.com/billerickson/8114100

  5. I found something interesting.

    In a single-cpt.php template, I was trying to show the links for the children posts of that cpt. Let’s say this is a ‘resort’ cpt wich is parent of ‘webcams’ and ‘hotels’ cpt’s, both set up as hierarchical.
    So I defined some arguments in an array: post_type (array), posts_per_page (-1), post_status (publish) and ‘post_parent’ ($post). Nothing fancy at all.

    I know that, for every parent post, there will be only one child post every time, so one resort will only have only one webcams child post and one hotels child post. In my mind, that gave me the option of doing a wp_query or not.

    So, Option-1 would be $webcams-child = get_posts( $args) and then I can echo the permalink for $webcams-child[0]->ID, for example. No wp_query here.

    Option-2 includes the usual custom loop through the possible results with wp_query, if and while, and then wp_reset_postdata.

    Now, according to the Query Monitor plugin, the first option (no wp_query) adds 3 more queries to the database, while the second option adds 4 more queries. BUT, if you delete the posts_per_page argument from $args, the first option ADDS 1 more query (so now you have 4 queries on the database) and the second option adds 2 more queries (so 6 queries to the database). In all cases, the memory usage stays more or less the same, no increments here.

    My poor logic guessing says that this is related to narrowing the scope of the arguments in the first place. But, curiously enough, deleting the post-status argument (which then, makes the system search in all published, draft, etc. elements) doesn’t add any query or memory usage at all. So I’m not sure. Of course, I did some experimentation and a badly optimized wp_query can easily become really expensive in terms of database queries, memory usage and response time, like multiplying them by a lot to obtain the same results.

    What I would like to know is then: if you add some more arguments to the $args, those 3 or 4 database queries could become less in number, even just 1 query? I think this is really interesting because my case is very simple, but others may encounter big issues due to a bad optimisation of the $args in the first place.

    1. When you do a WP Query, you’re actually doing 4 queries: the actual query for the posts you want, a query to determine the total number of posts matching the query (for pagination), all the post meta for the returned posts, and all the taxonomy terms for the returned posts. You can disable the ones you don’t need like so: https://www.billerickson.net/code/improve-performance-of-wp_query/

      You can also specify 'fields' => 'ids' to just receive a listing of the post IDs, not all the additional post information (title, content, excerpt…).

      1. Thanks Bill, I didn’t know that. It may be extremely useful in some cases.

        I’m not sure if this is clearly written in the Codex, I will check it out. I only have one pending doubt: if I delete the posts_per_page arg, it adds 2 more queries. Do you know what are they for?

        Thanks very much. I often read a lot of resources to understand WP and Genesis development, but I find myself keep coming back here and getting truly useful information. Thanks again.

      2. I’m not sure why you’re seeing an additional query. If you don’t include posts_per_page it uses the default in Settings > Reading, so that shouldn’t affect your query count. You can use Debug Bar and Query Monitor to see all queries run for the current request, which can help you figure out what’s happening.

Leave a comment