Unable to get pagination to work with combined WP Queries

So I have been battling with this for two days now and I can’t figure out how to fix the pagination with the combined wp_queries.

ORIGINAL CODE: This works perfectly, this has 4 posts shown and 7 posts in total and paginates through 2 pages:

enter image description here

$expertise_id = intval(array_key_exists('expertise_id', $_POST) ? $_POST['expertise_id'] : 0);
$is_ajax = array_key_exists('is_ajax', $_POST) ? $_POST['is_ajax'] : false;
$paged = intval(array_key_exists('paged', $_POST) ? $_POST['paged'] : 1);
$args = [
    'post_type' => ['work', FH_Report_Type::CPT_NAME],
    'posts_per_page' => FH_Work::ITEMS_PER_PAGE,
    'post_status' => ['publish'],
    'paged' => $paged
];
if (!is_null($expertise) || $expertise_id != 0) {
    $args['meta_query'] = [[
        'key' => 'expertise',
        'value' => '"' . (is_null($expertise) ? $expertise_id : $expertise->ID) . '"',
        'compare' => 'LIKE'
    ]];
}
$query = new WP_Query($args);
$content = '';
if ($query->have_posts()) {
    ob_start();
    get_template_part('template-parts/blocks/work-expertise-filter/work-items-template', null, ['query' => $query]);
    $content = ob_get_contents();
    ob_end_clean();
    wp_reset_postdata();
}

$result = ['content' => $content, 'has_pages' => $query->max_num_pages > $paged];

NEW CODE: This grabs 7 original posts, grabs the number of posts in relationship which is 6, checks relationship and if posts match, then exclude those, so at the end – I am stuck with 10 posts in total andd 3 pages of pagination (4 posts per page):

enter image description here

$expertise_id = intval(array_key_exists('expertise_id', $_POST) ? $_POST['expertise_id'] : 0);
$is_ajax = array_key_exists('is_ajax', $_POST) ? $_POST['is_ajax'] : false;
$paged = intval(array_key_exists('paged', $_POST) ? $_POST['paged'] : 1);
$args = [
    'post_status' => ['publish'],
    'post_type' => ['work', FH_Report_Type::CPT_NAME],
    'posts_per_page' => -1,
    'fields' => 'ids',
];
if (!is_null($expertise) || $expertise_id != 0) {
    $args['meta_query'] = [[
        'key' => 'expertise',
        'value' => '"' . (is_null($expertise) ? $expertise_id : $expertise->ID) . '"',
        'compare' => 'LIKE'
    ]];
}
if (get_field('featured_posts')) {
    $acf_post_ids = get_field('featured_posts', false, false);
    $acf_query = get_posts([
        'post_type' => 'any',
        'fields' => 'ids',
        'post__in' => $acf_post_ids,
        'orderby' => 'post__in',
        'posts_per_page' => -1,
    ]);
    $args['post__not_in'] = $acf_post_ids;
}
$wp_query = new WP_Query($args);
$merge_ids = array_unique(array_merge($acf_query, $wp_query->posts));
$args = [
    'post_type' => 'any',
    'post__in' => $merge_ids,
    'orderby' => 'post__in',
    'posts_per_page' => FH_Work::ITEMS_PER_PAGE,
    'paged' => $paged
];
$main_query = new WP_Query($args);
$content = '';
if ($main_query->have_posts()) {
    ob_start();
    get_template_part('template-parts/blocks/work-expertise-filter/work-items-template', null, ['query' => $main_query]);
    $content = ob_get_contents();
    ob_end_clean();
    wp_reset_postdata();
}
$result = ['content' => $content, 'has_pages' => $main_query->max_num_pages > $paged];

This is the template that its looping through:

$query = $args['query'];
$invert_tiles = array_key_exists('meta_query', $query->query);
$counter = $invert_tiles ? 1 : 0; // To define if is left or right template
?>
<?php while ($query->have_posts()) : $query->the_post(); ?>
    <?php
    $region_name = FH_Work::getInstance()->parent_region_display_name(get_the_ID());
    ?>
    <?php if ($counter % 2 == 0): ?>
        <!-- Image right -->
        <div class="container showcase img-right" data-aos="fade-up">
            <div class="row">
                <div class="col-12 not-rotated">
                    <div class="eyebrow medium location">
                        <span class="side-line side-line-after side-line-grey"><?php echo $region_name ?></span>
                    </div>
                </div>
                <div class="col-md-6 img px-0">
                    <!-- prettier ignore -->
                    <?php
                    $media_type_use_video = get_field('use_video', get_the_ID());
                    ?>
                    <?php if ($media_type_use_video): ?>
                        <div class="videos-wrap">
                            <video class="videos">
                                <!-- prettier ignore -->
                                <?php $video = get_field('video', get_the_ID()); ?>
                                <source src="<?php echo $video['url'] ?>"/>
                                Unable to load the video.
                            </video>
                        </div>
                    <?php else: ?>
                        <div class="imagery-wrap">
                            <img src="<?php echo get_the_post_thumbnail_url() ?>" alt="" class="imagery"/>
                        </div>
                    <?php endif ?>
                </div>
                <div class="col-md-6 content">
                    <div class="eyebrow medium location">
                        <span class="rotated side-line side-line-after side-line-grey"><?php echo $region_name ?></span>
                    </div>
                    <div class="row justify-content-md-end justify-content-lg-center align-items-md-center content-center">
                        <div class="col-sm-12 col-md-10 col-lg-8">
                            <div class="eyebrow medium bold brand"><?php the_field('client_name', get_the_ID()); ?></div>
                            <h2 class="bold title"><?php the_title() ?></h2>
                            <?php
                            $post = get_post(get_the_ID());
                            $cta_copy = $post->post_type == FH_Report_Type::CPT_NAME ? __('View Report', FLH_Translations::DOMAIN) : __('View Case Study', FLH_Translations::DOMAIN);
                            $cta_action = $post->post_type == FH_Report_Type::CPT_NAME ? get_field('file', get_the_ID()) : get_permalink();
                            ?>
                            <a href="<?php echo esc_url($cta_action) ?>"
                                <?php echo $post->post_type == FH_Report_Type::CPT_NAME ? 'target="_blank"' : '' ?>
                               class="btn-fh btn-secondary text-center"><?php echo $cta_copy ?></a>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    <?php endif; ?>
    <?php $counter++ ?>
<?php endwhile; ?>

THE PROBLEM:

When using the original query, the pagination works just fine and I am able to loop through JavaScript and load 2 pages in total of a combination of 7 posts.

In the new query, when I don’t add in a posts_per_page, it loads in all 10 posts, but as soon as I limited it down to 4 posts and I attempt to paginate, it loads in random posts, so not the remaining posts from $merge_ids.

All help is appreciated!

Here is the JS code if it’s needed:

function paginateWorkItems() {
        nextPage++;
        var data = {
            action: 'fh_paginate_work_items',
            is_ajax: true,
            paged: nextPage
        };

        if ($expertiseSelect != undefined && $expertiseSelect.find(':selected').data('expertise-id') != undefined) {
            data.expertise_id = $expertiseSelect.find(':selected').data('expertise-id');
        }

        $.ajax({
            type: 'POST',
            url: wp_ajax_url.full_url,
            data: data,
            dataType: 'json',
            success: function (response) {
                console.log(response);

                if (!response.hasOwnProperty('content') && !response.hasOwnProperty('has_pages')) {
                    return;
                }
                $block.find('.work-items-container').append(response.content);
                if (response.has_pages === false) {
                    $block.find('.cnt-pager').addClass('d-none');
                }
                setTimeout(function (){
                    $('.videos').hover(
                        function () {
                            $(this).get(0).play();
                        },
                        function () {
                            $(this).get(0).pause();
                        }
                    );
                }, 100);
            },
            error: function (response) {
            }
        });
    }
}

Source: Ask PHP

LEAVE A COMMENT