最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

custom post types - Pagination Error : Duplicate argument being outputted

programmeradmin3浏览0评论

I've been writing a custom search.php loop for some time now and I'm running into a weird problem. My php argument is outputting some unexpected results by repeating the template file.

Currently I have 56 posts total in my custom post type products

my $args array is configured as follows;

$search_query = get_search_query(); 

if ( get_query_var('paged') ) {
    $paged = get_query_var('paged');
} elseif ( get_query_var('page') ) { 
    $paged = get_query_var('page');
} else {
    $paged = 1;
}

$args = array(
    'post_type'         => 'products',
    'post_status'       => 'published',
    's'                 => $search_query,
    'paged'             => $paged,
    'posts_per_page'    => 15
);

// DO NOT REMOVE
global $query_string;
wp_parse_str( $query_string, $search_query );
$search = new WP_Query( $args );

My Loop is configured as follows;

<?php $i = 1; 

    if ( $search->have_posts() ) : 

        while ( $search->have_posts() ) : 

            $search->the_post();
            get_template_part( 'loop-templates/content-catalogue', get_post_format() ); 

            if($i % 3 == 0) {echo '<!-- Open a new deck --></div><div class="card-deck d-block d-lg-flex card-lg-gutters-3" data-aos="fade-up" data-aos-delay="50"><!-- Open a new deck -->';} $i++;

        endwhile; ?>

   <?php else : ?>

        <?php get_template_part( 'loop-templates/content', 'none' ); ?>

   <?php endif; ?>

   <?php understrap_pagination(); ?>
   <?php wp_reset_postdata(); ?>

My issue:

I should only have 4 pages in pagination. In reality I have 12 for some reason or another and each of the pages after the forth page is displaying my template file for no posts found. I.e.

<?php get_template_part( 'loop-templates/content', 'none' ); ?>

I'm stumped; and can't quite put my finger on what is wrong.

See my full search.php file.

I've been writing a custom search.php loop for some time now and I'm running into a weird problem. My php argument is outputting some unexpected results by repeating the template file.

Currently I have 56 posts total in my custom post type products

my $args array is configured as follows;

$search_query = get_search_query(); 

if ( get_query_var('paged') ) {
    $paged = get_query_var('paged');
} elseif ( get_query_var('page') ) { 
    $paged = get_query_var('page');
} else {
    $paged = 1;
}

$args = array(
    'post_type'         => 'products',
    'post_status'       => 'published',
    's'                 => $search_query,
    'paged'             => $paged,
    'posts_per_page'    => 15
);

// DO NOT REMOVE
global $query_string;
wp_parse_str( $query_string, $search_query );
$search = new WP_Query( $args );

My Loop is configured as follows;

<?php $i = 1; 

    if ( $search->have_posts() ) : 

        while ( $search->have_posts() ) : 

            $search->the_post();
            get_template_part( 'loop-templates/content-catalogue', get_post_format() ); 

            if($i % 3 == 0) {echo '<!-- Open a new deck --></div><div class="card-deck d-block d-lg-flex card-lg-gutters-3" data-aos="fade-up" data-aos-delay="50"><!-- Open a new deck -->';} $i++;

        endwhile; ?>

   <?php else : ?>

        <?php get_template_part( 'loop-templates/content', 'none' ); ?>

   <?php endif; ?>

   <?php understrap_pagination(); ?>
   <?php wp_reset_postdata(); ?>

My issue:

I should only have 4 pages in pagination. In reality I have 12 for some reason or another and each of the pages after the forth page is displaying my template file for no posts found. I.e.

<?php get_template_part( 'loop-templates/content', 'none' ); ?>

I'm stumped; and can't quite put my finger on what is wrong.

See my full search.php file.

Share Improve this question edited Jul 2, 2019 at 13:08 Lewis asked Jul 2, 2019 at 13:03 LewisLewis 4083 silver badges16 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 2

This is another example of what is by far the most common mistake I've seen in WordPress development. I don't think it's even close to whatever the next most common is. I'm very curious as to what documentation or tutorials are out there that are teaching this approach to queries, or what could be done to the official documentation to make this clearer.

The problem is essentially that you're using a pagination function, understrap_pagination() which is (correctly) using the status of the main query (the global $wp_query object) to determine the pages to show, but your template is using your own custom query ($search) to output the posts. If these queries have mismatched arguments, a different number posts per page, or a differing current page number, then you're going to get weirdness like this.

All the main WordPress templates, like index.php, archive.php, search.php, have already queried the correct posts for you, based on the URL request, and made them accessible via the main loop:

if ( have_posts() ) : while( have_posts() ) : the_post();

endwhile; endif;

(Notice the lack of any object variable being used here)

And functions like pagination and next/previous links are all built to use this query to produce accurate output. If you use a separate query or modify this query incorrectly then those functions that depend on the state of the main query are going to give what looks like incorrect output. Pagination is the most common of these.

Your search.php loop needs to look like this:

$i = 1; 

if ( have_posts() ) : 
    while ( have_posts() ) : 
        the_post();

        get_template_part( 'loop-templates/content-catalogue', get_post_format() ); 

        if( $i % 3 == 0 ) {
            echo '<!-- Open a new deck --></div><div class="card-deck d-block d-lg-flex card-lg-gutters-3" data-aos="fade-up" data-aos-delay="50"><!-- Open a new deck -->'; 
        }

        $i++;

    endwhile;
else : 
    get_template_part( 'loop-templates/content', 'none' );
endif;

understrap_pagination();
wp_reset_postdata();

Note that $search isn't used anywhere. This is because you must use the main query loop.

This brings us to the issue of why $search exists to begin with. From what I can tell from your full search.php template, you have 2 search forms: a "global" search, and a "catalogue" search, and you're using the $search query when the user performs a catalogue search. Creating a separate query is not the correct way to do this. For one thing, it means that regardless of which search the user performed you're performing both searches, which is ineffecient. Secondly, it's causing you this pagination issue.

So what you need to do is make both the catalogue and global versions of your template use the same main loop, as I described above. Then you need to use the pre_get_posts hook to modify the main query based on which query the user performed. From what I can tell the main thing you do is change the number of posts per page, and limit the post type to products. You can do this with this code in your theme's functions.php file:

function wpse_341991_catalogue_search( $query ) {
    if ( $query->is_search() ) {
        if ( 'catalogueSearch' === $_GET['formName'] ) {
            $query->set( 'post_type', 'products' );
            $query->set( 'posts_per_page', 15 );
        }
    }
}
add_action( 'pre_get_posts', 'wpse_341991_catalogue_search' );

Now whenever a user searches with your catalogue search form, the main query will show you the results you want, and the pagination functions should function like normal.

One last thing though. post_type is already a valid query argument that you can include in a search form. So if you want to change the post type searched by a form, you can just add a hidden field with the name set to post_type and the value set to the post type that you're searching:

<input type="hidden" name="post_type" value="products">

This means you omit your formName input, and reduce the pre_get_posts function to:

function wpse_341991_catalogue_search( $query ) {
    if ( $query->is_search() && 'products' === $query->get( 'post_type' ) ) {
        $query->set( 'posts_per_page', 15 );
    }
}
add_action( 'pre_get_posts', 'wpse_341991_catalogue_search' );

And in your template, rather than checking:

if ( strcmp( $formIdentifier, 'globalSearch' )) {

You can check:

if ( 'products' !== get_query_var( 'post_type' ) ) {
发布评论

评论列表(0)

  1. 暂无评论