Software Engineering in WordPress, PHP, and Backend Development

Search: “wp_query” (Page 1 of 10)

We found 48 results for your search.

Properly Calculating Page Offset in Custom WordPress Queries

[…] pagination. One of the areas that I see most confusing – again for myself as well – is properly calculating page offsets especially when working with the WP_Query offset parameter. The thing is, I think it can be much more simplified (or, perhaps, demystified?) when visualizing the data that you’re working with, and knowing how to use some of the existing API links. So here’s what you need to know in order to get pagination working when working with the WP_Query offset, page, and number parameters. A Few Assumptions There’s several things I’m assuming while writing this article: You’re using pretty permalinks – that is, /%postname%/ – some variation thereof, or are comfortable enough to track with code regardless of the permalink setting. You’ve at least heard of functions such as get_query_var, next_posts_link, previous_posts_link, and posts_nav_link You’ve done some work with WP_Query Nothing too complicated, right? Visualizing Pagination When working with WP_Query parameters specifically for pagination, there are really only three parameters that factor into the whole operation: number. This is the number of posts that you want to display on the page at any given time. page. The is the page that’s currently being displayed. offset. This is where the query begins pulling posts. For example, if you’re on page one, then the offset will be zero; otherwise, it will be something else to “bypass” posts that’ve already been display. Before looking at any code or trying to explain any further, here’s a way to visualize what’s going on when you’re paging through your posts: Visualizing Post Pagination in WordPress In the photo above, notice that there’s a set of seven pages. This is represented by max_num_pages which will be used momentarily. Next, only two posts will be displayed per page. Sure, it’s small but it works well enough for a demonstration. Finally, the offset is actually represented by a formula. Basically, it’s the current page number multiplied by the current page number less one. This is what trips developers out more than anything else. Understanding WP_Query Offset For Pagination Offsets and Off-By-One First, offset is nothing more than a parameter that tells WordPress where to begin pulling posts. If you’re on the first page, the offset should be zero. If you’re on page two, then it should be however many posts you’ve already displayed (less one, since we start counting at zero) multiplied by the page that you’re on. Make sense? Look at it this way: Page 1: (1 – 1) * 1 = 0 Page 2: (2 – 1) * 1 = 1 Page 3: (3 – 1) * 1 = 2 Remember: The final value calculated for the offset is usually one less than what you’d expect because offsets start counting at zero. Writing The Query At this point, the only other missing piece is being able to calculate which page we’re on. Luckily, WordPress makes this available as a query string variable that can be accessed by using get_query_var. The best way to get the current page is this: // If the query var is set use it; otherwise, initialize it to one. $page = get_query_var( ‘paged’ ) ? get_query_var( ‘paged’ ) : 1; And yes, WordPress stores it in a variable called “paged.” From there, we can begin writing the query. I’m assuming that we’re going to be doing something simple like pulling back posts ordered by descending date. Obviously, your implementation may vary, but the pagination part should be the same: // First, initialize how many posts to render per page $display_count = 2; // Next, get the current page $page = get_query_var( ‘paged’ ) ? get_query_var( ‘paged’ ) : 1; // After that, calculate the offset $offset = ( $page – 1 ) * $display_count; // Finally, we’ll set the query arguments and instantiate WP_Query $query_args = array( ‘post_type’ => ‘post’, ‘orderby’ => ‘date’, ‘order’ => ‘desc’, ‘number’ => $display_count, ‘page’ => $page, ‘offset’ => $offset ); $custom_query = new WP_Query ( $query_args ); /* * Use your query here. Remember that if you make a call to $custom->the_post() * you’ll need to reset the post data after the loop by calling wp_reset_postdata(). */ This will get you all you need in order to have […]

How To Setup Custom Queries For WP_Query Pagination

One of the nicest things about using WP_Query is that it allows you to completely customize the data that you’re bringing back to the front end. For those of you who are completely unfamiliar with this API, it’s a powerful class that allows you to custom tailor a query against the WordPress database for retrieving information about posts, pages, custom post types, and so on. If you’re using one of the more common features of WordPress, such as those mentioned above, then it’s relatively easy to get started; however, if you’re doing more complicated work, such as including multiple custom queries in a single view, then there are some challenges that you may discover. Personally, I’ve been working on a project where I have two custom queries running in a template and I needed to paginate the results. The problem is that using the usual functions for doing this, that is: posts_nav_link previous_posts_links next_posts_links Were not working as expected. Ultimately, it required me passing a little bit more information to the query’s arguments array and to the pagination link functions. Here’s how you can setup WP_Query Pagination to work properly in custom queries. A Few Assumptions There are two assumptions that I’m making about your setup: You’re using pretty permalinks. That is, your permalink structure includes something like /%postname%/. You’re familiar with get_query_var specifically or pagination. Assuming that you’re familiar with both of these, you should be good to go from defining your custom queries and for getting pagination to work correctly without any custom helper functions and by using the native WordPress API. A Working Example Defining The Query Let’s assume that we’re just going to be pulling back a set of records for a custom post type called goals. First, we need to define the arguments for the query. Personally, I think that defining the arguments in an array and then passing the array to the WP_Query class makes for more readable, manageable code, but that’s completely subjective. // First, get a reference to the current author of the posts in this listing $current_author = ( isset($_GET ) ) ? get_user_by( ‘slug’, $author_name ) : get_userdata( intval( $author ) ); // Next, define a way to get the current offset function example_get_offset() { $number = 10; $page = get_query_var( ‘paged’ ) ? get_query_var( ‘paged’ ) : 1 return 1 == $page ? ( $page – 1 ) : ( ( $page – 1 ) * $number ); } // end example_get_offset // After that, set the arguments for the query $args = array( ‘post_type’ => array( ‘goal’ ), ‘orderby’ => ‘date’, ‘order’ => ‘desc’, ‘posts_per_page’ => 10, ‘offset’ => example_get_offset(), ‘paged’ => get_query_var( ‘page’ ) ? get_query_var( ‘page’ ) : 1, ‘author’ => $current_author->ID ); // Finally, instantiate the query $query = new WP_Query( $args ); The code comments should be relatively clear; however, there are two main arguments in the $args array that are worth noting: posts_per_page. This is somewhat of an arbitrary value, but this simply tells WordPress […]

How To Efficiently Exclude Categories From The WordPress Loop

When it comes to writing custom queries in WordPress, ` WP_Query` is the API to use. And I could be mistaken, but I do see a lot of people urging developers to avoiding using `query_posts` in WordPress in favor this newer-ish API. But the thing is that `query_posts` still has its place in WordPress development namely in modifying the results of the data queried for The Loop when rendering blog content; however, one of the the biggest caveats is the performance that `query_posts` can have on the performance of the blog. I’ve recently been working on a plugin where I needed to exclude posts from The Loop based on the category. At first, I was going to use `query_posts` but I ultimately hit a few snags, so here’s an alternative way to exclude categories from the WordPress Loop. Exclude Categories From WordPress Loop The WordPress Codex Documentation for query_posts. First, here are a few nuances about the function that you need to know about `query_posts`. From the Codex: query_posts a way to alter the main query that WordPress uses to display posts. It does this by putting the main query to one side, and replacing it with a new query. But there’s a very important thing to note regarding this function: It should be noted that using this to replace the main query on a page can increase page loading times, in worst case scenarios more than doubling the amount of work needed or more. All of that to say is that when you’re working with `query_posts`, then you need to be really careful with the work that you’re doing because you could, at worst, exhaust your PHP memory limits and thus tank the entire site. So what’s our alternative? Working with pre_get_posts `pre_get_posts` is a hook that’s available to us that accepts the global WordPress query by reference so that we can modify the query variables prior to having the query actually run. So, for example, the basic function would look something like this: function demo_exclude_category( $wp_query ) { // TODO } add_action( ‘pre_get_posts’, ‘demo_exclude_category’ ); Again, `$wp_query` is passed to `demo_exclude_category` by reference so we’re able to reference to modify the query variables however needed prior to having the query actually run. But there are two ways to do this: Procedural Programming and Object-Oriented Programming. Procedural Programming Procedural programming is what you’re used to seeing in things like `functions.php` as well as various plugins. In short, all of the functions are prefixed with a unique identifier and do not reside with inside a class. So let’s say we wanted to exclude the first category from The Loop using procedural programming in either `functions.php` or in a plugin. Here’s what’d be required: Define the function Register the function to the `pre_get_posts` hook function demo_exclude_category( $wp_query ) { // Add the category to an array of excluded categories. In this case, though, // it’s really just one. $excluded = array( ‘-1’ ); // Note that this is a cleaner way to write: $wp_query->set(‘category__not_in’, $excluded); set_query_var( ‘category__not_in’, $excluded ); } add_action( ‘pre_get_posts’, ‘demo_exclude_category’ ); Easy enough, right? In fact, the object-oriented approach isn’t much more complicated. Object-Oriented Programming In the case of object-oriented programming, it’s practically the same thing; however, you define the hook in the constructor and the method as a class function: class Example_Plugin { public function __construct() { add_action( ‘pre_get_posts’, array( $this, ‘exclude_first_category_posts’ ) ); } public function exclude_first_category_posts( $wp_query ) { // Only remove them from the blog page – display them on Search and Archive pages if ( ! is_search() && ! is_archive() ) { // Add the category to an array of excluded categories. In this case, though, it’s really just one. $excluded = array( ‘-1’ ); // This is a cleaner way to write: $wp_query->set( ‘category__not_in’, $excluded ); set_query_var( ‘category__not_in’, $excluded ); } } } Notice above that I’m actually only performing the exclusion on the homepage rather than on Search pages and on Archive pages. Anyway, when I was attempting to do something similar with `query_posts` there […]

Writing Clean, Maintainable Custom WordPress Queries

[…] Query for the 10 most recent posts by the specified users $args = array( ‘post_type’ => ‘post’, ‘posts_per_page’ => 10, ‘author’ => $featured_user_ids ); $the_query = new WP_Query( $args ); // Finally, loop through the posts while ( $the_query->have_posts() ) { $the_query->the_post(); /* Snipped for brevity, but this is where the markup would render post data. */ } // end while wp_reset_postdata(); It’s relatively easy to read, but it’s incredibly long. This makes makes working with the given template a bit of a hassel because you have to wade through this information prior to actually marking up the data. By abstracting this into its own method, you can greatly simplify the foreach loop and, consequently, the template that renders this data. After First, you’d setup a function in functions.php specifically for returning the query. Obviously this will look exactly the same as above – it’s simply encapsulating the calls to the WordPress API: function example_get_featured_user_posts() { // get the featured editors $editor_query = new WP_User_Query( array( ‘role’ => ‘editor’, ‘meta_key’ => ‘featured’, ‘meta_value’ => ‘yes’, ‘meta_compare’ => ‘=’, ‘number’ => 5 ) ); $editors = $editor_query->get_results(); // get the featured admins $administrator_query = new WP_User_Query( array( ‘role’ => ‘administrator’, ‘meta_key’ => ‘featured’, ‘meta_value’ => ‘yes’, ‘meta_compare’ => ‘=’, ‘number’ => 5 ) ); $admins = $administrator_query->get_results(); // store them all as users $users = array_merge( $admins, $editors ); // Store the author ID’s in a CSV removing the last comma $featured_user_ids = ”; foreach( $users as $user ) { $featured_user_ids .= $user->ID . ‘,’; } // end foreach $featured_user_ids = substr( $featured_user_ids, 0, strlen( $featured_user_ids ) – 1 ); // Query for the 10 most recent posts by the specified users $args = array( ‘post_type’ => ‘post’, ‘posts_per_page’ => 10, ‘author’ => $featured_user_ids ); $the_query = new WP_Query( $args ); return $the_query; } // end example_get_featured_user_posts Next, you’d then make a call to this function in the foreach to render the data: $users_query = example_get_featured_user_posts(); while( $users_query->have_posts() ) { $users_query->the_post(); /* Snipped for brevity, but this is where the markup would render post data. */ } // end while wp_reset_postdata(); Technically, I think you can make […]

How To Use WP_User_Query For WordPress User Queries

[…] its API with each new release. Recall that The Right Way™ was once to use query_posts in order to retrieve post data. However, as of recent releases, WP_Query has become The Right Way™ to do it. It’s a cleaner interface, more powerful, and is the way that’s backed by Automattic and the developer community at large for properly querying the database for a variety of data. All of that to say that this is strikingly similar – just as we’ve got from query_posts to WP_Query, we’re going from get_users to WP_User_Query. It’s all about forward thinking. The Details on WP_User_Query The Codex article will provide much more information that I have below; however, I want to make sure that I highlight exactly what WP_User_Query offers if for no other reason to remind myself of what it can do. Straight from the documentation: The WordPress User Query class allows querying the user database and deprecates the WP_User_Search class since Version 3.1. WP_User_Query… An array of arguments from which it will use to query the database for results Returns either an array of row objects or an array of user objects To use the class – as with many in the WordPress API – you define the array of arguments and then pass them to the constructor of the WP_User_Query while instantiating the class. Assuming that your arguments are stored in an array referenced by $args, it would look like this: $user_query = new WP_User_Query( $args ); Then, to get your array of results, you’d call: $user_query->get_results() Easy, isn’t it? Overall, I’m a fan of this graduate shift to class-based queries rather than using global-level functions, but that’s because I’m more of a […]

« Older posts

© 2024 Tom McFarlin

Theme by Anders NorenUp ↑