40

I see many people prefer to use pre_get_posts hook instead of query_posts Yay! So pre_get_posts filters a WP_Query object which means anything you could do via query_posts() you can do via $query->set() and $query->get(). In particular we can make use of the meta_query attribute (see Codex): $meta_query = array( array( ...


26

Set orderby to post__in. This preserves post ID order given in the post__in array (available with Version 3.5). $args = array ( 'posts_per_page' => -1, 'post__in' => $ids, 'orderby' => 'post__in' );


25

I know this is an old question, but it is a bit confusing and hopefully will help someone. The reason that `$query->set doesn't work is because the query has already been parsed and now we need to also update the tax_query object also. Here is how I did it: function my_tax_query( $query ) { $package_id = 12345; $tax_query = array( 'taxonomy' ...


17

To achieve adding a custom sortable column to the WP_List_Table of your post type within the WordPress administration back-end dashboard, you will need to do the following: Replace all occurrences of YOUR-POST-TYPE-NAME with your actual post type name. Replace all occurrences of YOUR-TAXONOMY-NAME with your actual taxonomy name. Replace all occurrences of ...


17

Improve your conditional to include a check for post type being queried. It can be done via WP_Query::get method So, where you have if ( !is_admin() ){ $query->set( 'meta_key', '_ct_selectbox_52f65ae267764' ); $query->set( 'meta_value', $city ); return; } replace with if ( ! is_admin() && in_array ( $query->get('post_type'), ...


16

As of Wordpress 3.7 a new action named parse_tax_query was added exactly for this purpose. function kia_no_child_terms($wp_query) { $wp_query->tax_query->queries[0]['include_children'] = 0; } add_action('parse_tax_query', 'kia_no_child_terms'); This hook modifies the values of both query_vars and tax_query. Using the pre_get_posts method ...


15

I'll take another shot. The following should modify the main query, such that it will include in its loop any posts that belong to no term of the Edition custom taxonomy. add_filter('pre_get_posts','better_editions_archive'); function better_editions_archive( $query ) { if ( $query->is_tax( 'edition' ) && $query->is_main_query() ) { ...


15

Easy Peasy, just tested 2018, using in production currently. $query->set( 'meta_query', array( 'relation' => 'OR', array( 'key' => 'custom_meta_key', 'compare' => 'EXISTS' ), array( 'key' => 'custom_meta_key', 'compare' => 'NOT EXISTS' ) ) ); $query->set( 'orderby', 'meta_value title'...


14

pre_get_posts will run the same query, so both will take same time. But, If you utilize pre_get_posts action you will save one or more SQL queries. Right now, WordPress is running default query and then you run your query with this function which replace the results of the default query (resulting, default query is of no use). Below is how you can move your $...


14

As Milo said : $query->set('meta_key', 'wpcf-object-sold-status' ); $query->set('orderby', array('meta_value' => 'ASC', 'date' => 'DESC')); // $query->set('order', 'ASC DESC' ); // not needed Relevant link: https://make.wordpress.org/core/2014/08/29/a-more-powerful-order-by-in-wordpress-4-0/


14

I finally got it working, but not with the code in my question. I totally scrapped that whole idea and restarted going in a new direction. NOTE: If anyone is ever able to sort out the issues in my question, feel free to post an answer. Also, if you have any other solutions, feel free to post an answer. REWORKED CLASS AND SOLUTION: What I tried to do here ...


13

When 'pre_get_posts' is fired, there are a lot of things that WordPress has already done like setup all the query variables (also the query you don't send) and setup all the conditional properties (all the is_* properties). So, if you want completely replace the query you should reset all that things and set your own. In fact, even if your code works, ...


12

Here is an approach to account for sticky posts by getting the number of sticky posts (if any) and include that in the calculation posts_per_page parameter: add_action('pre_get_posts', 'ad_custom_query'); function ad_custom_query($query) { if ($query->is_main_query() && is_home()) { // set the number of posts per page $...


10

I modify WordPress query from functions.php: //unfortunately, "IS_PAGE" condition doesn't work in pre_get_posts (it's WORDPRESS behaviour) //so you can use `add_filter('posts_where', ....);` OR modify "PAGE" query directly into template file add_action( 'pre_get_posts', 'myFunction' ); function myFunction($query) { if ( ! is_admin() && $...


10

Late answer as the most upvoted answer will break your query and simply isn't true in some major points. The main WP_Query and it's filters First, WordPress internally uses query_posts() (a thin wrapper around WP_Query that shouldn't be used in themes or plugins) to do a WP_Query. This WP_Query is acting as the main loop/query. This query will run through ...


10

This method will return all of the posts including those with and without the requested meta_key, but it will do weird things when ordering. add_action('pre_get_posts', 'my_stuff'); function my_stuff ($qry) { $qry->set( 'meta_query', array( 'relation' => 'OR', # Matches to this meta_query should be added to those ...


9

It does't work because you can't use set to change all query vars. Simplest way to do the trick is set 's' to an empty string: add_action( 'pre_get_posts', function( $query ) { if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) { $taxquery = array( ... ); $query->set( 'tax_query', $taxquery ); $...


8

Your filter has a bug in it, namely when you call is_main_query, you're not checking if the passed query is the main query, your checking if the currently active query is the main query, which will always be true. So instead try this: add_action( 'pre_get_posts', 'some_name'); function some_name($query) { if ($query->is_front_page() && $...


8

Instead of trying to display all the matching events on your by-date page, you could try to display through ?post_type=event like this: function rewrite_rule_by_date() { add_rewrite_rule('by\-date/([0-9]{4}\-[0-9]{2}\-[0-9]{2})$', 'index.php?post_type=event&event_date=$matches[1]', 'top'); } add_action( 'init', 'rewrite_rule_by_date' ); function ...


8

After a bit of investigation... If you pass a category to is_category it uses get_queried_object to grab data-- see the source. get_queried_object returns NULL for categories that do not exist. You can demonstrate that with: function custom_posts_per_page($query) { var_dump(get_queried_object()); } add_filter( 'pre_get_posts', 'custom_posts_per_page' ); ...


7

Just to outline some improvements to the accepted answer since WordPress evolved over the time and some things are different now (five years later): pre_get_posts is a filter, for altering any query. It is most often used to alter only the 'main query': Actually is an action hook. Not a filter, and it will affect any query. The main query appears in ...


6

Please check out the answers at When to use WP_query(), query_posts() and pre_get_posts. It is a great ressource if you have any doubts in mind.


6

In regards to your decision not to use WP_Query, pre_get_posts is actually an excellent choice to make, rather than creating a new instance of WP_Query. In fact, pre_get_posts is exactly what you should be using when you want to change the main query. Rather than executing a separate query on each page load, it modifies the main query's parameters before it ...


6

Edit: This answer was written before I realised the OP has a static front page. I've left it here in case it's useful to anyone else and added a second answer for the static front page case. This will add your custom post type to the home page main loop: add_action( 'pre_get_posts', 'wpse_242473_add_post_type_to_home' ); function ...


5

$caid is unknown inside the function, unless declared global. $caid = '-1'; function exclude_category( $query ) { global $caid; if ( $query->is_home() && $query->is_main_query() ) { $query->set( 'cat', $caid ); } } add_action( 'pre_get_posts', 'exclude_category' ); // Edit Do you need the variable outside the function ...


5

Well, you SHOULDN'T use pre_get_posts, as it will alter ALL the queries in the site. Also, the query made by the recent posts plugin is not the main query. The main query is made for displaying the current page, after parsing the query variables from URL, and it is responsible, among other things for the current page template. What you SHOULD do is ...


5

You can access query variables (including custom ones) via the WP_Query::get() method. For example: $my_query = new WP_Query( array( ... 'wpse105219_custom_var' => 'foobar', ... ) ); To 'catch' this at pre_get_posts: add_action( 'pre_get_posts', 'wpse105219_pre_get_posts', 10 ); function wpse105219_pre_get_posts( $query ){ if( $...


5

Firstly, you are invoking an infinite loop, which causes the memory exhaustion. To avoid it, put the following at the beginning of your function: // avoid infinite loop remove_action( 'pre_get_posts', __FUNCTION__ ); It makes sure the you are not hooking it into pre_get_posts over and over again, re-initiating your get_posts() call over and over again. ...


5

Here is an answer I recently did on another question, the same as your. Because the answer was never upvoted or accepted, I could not mark this question as duplicate, so I have deleted the answer in the other post and reposting it here. Please note, some points are not aimed at this issue and can be ignored, also, you will just need to make a few ...


5

Maybe a bit late … add_action( 'pre_get_posts', function($query) { if ( !is_admin() && $query->is_main_query() && is_post_type_archive( '[your_post_type]' ) ) { $query->set('meta_query', array( '_property_price' => array( 'key' => '_property_price', ), ...


Only top voted, non community-wiki answers of a minimum length are eligible