This link solves the problem but it’s only for the main query. What if you are using a custom query? How can you modify the answer below:
add_action('pre_get_posts', 'ad_custom_query');
function ad_custom_query($query) {
if ($query->is_main_query() && is_home()) { //how can we for specific custom query?
// set the number of posts per page
$posts_per_page = 12;
// get sticky posts array
$sticky_posts = get_option( 'sticky_posts' );
// if we have any sticky posts and we are at the first page
if (is_array($sticky_posts) && !$query->is_paged()) {
// counnt the number of sticky posts
$sticky_count = count($sticky_posts);
// and if the number of sticky posts is less than
// the number we want to set:
if ($sticky_count < $posts_per_page) {
$query->set('posts_per_page', $posts_per_page - $sticky_count);
// if the number of sticky posts is greater than or equal
// the number of pages we want to set:
} else {
$query->set('posts_per_page', 1);
}
// fallback in case we have no sticky posts
// and we are not on the first page
} else {
$query->set('posts_per_page', $posts_per_page);
}
}
}
2 Answers
I think we can try the following: (NOTE: This is untested but should in theory work, but remember, it is untested and can be buggy)
add_action('pre_get_posts', 'ad_custom_query');
function ad_custom_query($query) {
// No other checks should be necessary
if ( $query->get( 'custom_query' ) === 1 ) ) {
// set the number of posts per page
$posts_per_page = 12;
// get sticky posts array
$sticky_posts = get_option( 'sticky_posts' );
// if we have any sticky posts and we are at the first page
if (is_array($sticky_posts) && !$query->is_paged()) {
// counnt the number of sticky posts
$sticky_count = count($sticky_posts);
// and if the number of sticky posts is less than
// the number we want to set:
if ($sticky_count < $posts_per_page) {
$query->set('posts_per_page', $posts_per_page - $sticky_count);
// if the number of sticky posts is greater than or equal
// the number of pages we want to set:
} else {
$query->set('posts_per_page', 1);
}
// fallback in case we have no sticky posts
// and we are not on the first page
} else {
$query->set('posts_per_page', $posts_per_page);
}
}
}
You can now just do run the following custom query
$args = [
'custom_query' => 1, // Note, this has to be an integer, '1' will not work
'paged' = > $paged
// I would just add all the other parameters in the pre_get_posts action
];
$q = new WP_Query( $args );
FEW NOTES:
-
Because we will only target queries where the new
custom_query
parameter is set to1
, we should not need the checks like!is_admin()
oris_main_query()
-
Because we are running a
pre_get_posts
action on our custom query, I would just set thecustom_query
andpaged
parameter in query arguments. Any other parameters I would simply just add in thepre_get_posts
action. -
If you need to run a second query with different parameter and/or values, you can simply set
custom_query
to2
and then just check in if the$query->get( 'custom_query' )
has a value of2
, likeif ( $query->get( 'custom_query' ) === 2 ) {
-
I have just copied your code and added the new parameter check, I have not worked through your code or changed anything