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

theme development - Any tag pagination page (except the 1st page) loads index.php template instead of tag.php

programmeradmin4浏览0评论

Created my first custom theme from scratch and I'm trying to do a listing of all posts with the same tag.

In tag.php I display all posts with that specific tag via a WP_Query and I'm trying to implement the pagination for that listing (using paginate_links()). Page links seem to be outputted correctly. Also the first page looks good.

What I don't understand is that when I go on to the next tag page (or to any of the page links outputted from my tag.php template e.g. http://127.0.0.1/wp_site/tag/test_tag/page/2/) the content from index.php is being displayed.

What am I actually missing for displaying the subsequent tag pages correctly?

tag.php template CODE:

<?php get_header(); ?>
<div class="">
    <div id="primary" class="content-area">
        <main id="main" class="site-main" role="main">
            <?php if (have_posts()) : ?>
                <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
                    <header class="entry-header">
                        <h1 class="entry-title">Other entries related to &#39;<?php single_tag_title(); ?>&#39;</h1>
                    </header><!-- .entry-header -->
                    <div class="entry-content"></div><!-- .entry-content -->
                </article><!-- #post-## -->
                <div>   
                    <?php while (have_posts()) : the_post(); ?>
                       <?php
                            $tagId = get_queried_object()->term_id;
                            $postType = get_post_type();
                        ?>
                    <?php endwhile; ?>
                    <?php
                        $htmlOutput = '';
                        /* the 'terms' ID is the testimonial category parent id */
                        $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
                        $args = [
                              'post_type' => 'testimonials-widget', 
                              'tag_id' => $tagId,
                              'posts_per_page' => 3,
                              'paged' => $paged,
                              'tax_query' => [
                                    [
                                        'taxonomy' => 'category',
                                        'field'    => 'term_id',
                                        'terms'    => '8',
                                    ]
                                ],
                        ];    
                        $post_query = new WP_Query($args);
                        $contentHtml = '';
                        if($post_query->have_posts() ) {
                            $posts = $post_query->posts;
                            foreach($posts as $post) {
                                // generate html output
                            }
                        }
                        wp_reset_postdata();
                        echo $contentHtml;
                    ?>
                </div>
                <div class="mainContentWrapperCls">
                <?php 
                    echo paginate_links( array(
                        'base'         => str_replace( 999999999, '%#%', esc_url( get_pagenum_link( 999999999 ) ) ),
                        'total'        => $post_query->max_num_pages,
                        'current'      => max( 1, get_query_var( 'paged' ) ),
                        'format'       => '?paged=%#%',
                        'show_all'     => false,
                        'type'         => 'plain',
                        'end_size'     => 2,
                        'mid_size'     => 1,
                        'prev_next'    => true,
                        'prev_text'    => sprintf( '<i></i> %1$s', __( '&lt;&lt; Previous page', 'text-domain' ) ),
                        'next_text'    => sprintf( '%1$s <i></i>', __( 'Next page &gt;&gt;', 'text-domain' ) ),
                        'add_args'     => false,
                        'add_fragment' => '',
                    ) );
                ?>
            </div>
            <?php else : ?>
                <h1>No posts were found.</h1> 
            <?php endif; ?>
        </main><!-- #main -->
    </div><!-- #primary -->
</div><!-- .wrap -->
<?php get_footer(); ?>

Note: I created a new query with WP_Query in tag.php. The reason why I did this is because I didn't know how to generate the type of pagination I needed (<Prev 1 2 3 Next> style) via paginate_links(), with the main query.

Theme functions.php CODE:

<?php
    function myCustomThemeScriptEnqueue() {
        // Theme stylesheet, js
        wp_enqueue_style('myCustomTheme-style', get_stylesheet_uri(), array(), '1.0.0', 'all');
    }

    function myCustomThemeThemeSetup() {
        add_theme_support('menus');
        add_post_type_support( 'page', 'excerpt' );
    }

    function nllTagFilter($query) {
        if ($query->is_main_query()) {
            if ($query->is_tag) {
                $post_types = get_post_types();
                $query->set('post_type', $post_types);
            }
        }
    }

    add_action('pre_get_posts','nllTagFilter');

    add_action('wp_enqueue_scripts', 'myCustomThemeScriptEnqueue');
    add_action('init', 'myCustomThemeThemeSetup');

    add_theme_support( 'post-thumbnails' );
    set_post_thumbnail_size( 150, 150 );
?>

This is my theme's file-structure so far:

Created my first custom theme from scratch and I'm trying to do a listing of all posts with the same tag.

In tag.php I display all posts with that specific tag via a WP_Query and I'm trying to implement the pagination for that listing (using paginate_links()). Page links seem to be outputted correctly. Also the first page looks good.

What I don't understand is that when I go on to the next tag page (or to any of the page links outputted from my tag.php template e.g. http://127.0.0.1/wp_site/tag/test_tag/page/2/) the content from index.php is being displayed.

What am I actually missing for displaying the subsequent tag pages correctly?

tag.php template CODE:

<?php get_header(); ?>
<div class="">
    <div id="primary" class="content-area">
        <main id="main" class="site-main" role="main">
            <?php if (have_posts()) : ?>
                <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
                    <header class="entry-header">
                        <h1 class="entry-title">Other entries related to &#39;<?php single_tag_title(); ?>&#39;</h1>
                    </header><!-- .entry-header -->
                    <div class="entry-content"></div><!-- .entry-content -->
                </article><!-- #post-## -->
                <div>   
                    <?php while (have_posts()) : the_post(); ?>
                       <?php
                            $tagId = get_queried_object()->term_id;
                            $postType = get_post_type();
                        ?>
                    <?php endwhile; ?>
                    <?php
                        $htmlOutput = '';
                        /* the 'terms' ID is the testimonial category parent id */
                        $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
                        $args = [
                              'post_type' => 'testimonials-widget', 
                              'tag_id' => $tagId,
                              'posts_per_page' => 3,
                              'paged' => $paged,
                              'tax_query' => [
                                    [
                                        'taxonomy' => 'category',
                                        'field'    => 'term_id',
                                        'terms'    => '8',
                                    ]
                                ],
                        ];    
                        $post_query = new WP_Query($args);
                        $contentHtml = '';
                        if($post_query->have_posts() ) {
                            $posts = $post_query->posts;
                            foreach($posts as $post) {
                                // generate html output
                            }
                        }
                        wp_reset_postdata();
                        echo $contentHtml;
                    ?>
                </div>
                <div class="mainContentWrapperCls">
                <?php 
                    echo paginate_links( array(
                        'base'         => str_replace( 999999999, '%#%', esc_url( get_pagenum_link( 999999999 ) ) ),
                        'total'        => $post_query->max_num_pages,
                        'current'      => max( 1, get_query_var( 'paged' ) ),
                        'format'       => '?paged=%#%',
                        'show_all'     => false,
                        'type'         => 'plain',
                        'end_size'     => 2,
                        'mid_size'     => 1,
                        'prev_next'    => true,
                        'prev_text'    => sprintf( '<i></i> %1$s', __( '&lt;&lt; Previous page', 'text-domain' ) ),
                        'next_text'    => sprintf( '%1$s <i></i>', __( 'Next page &gt;&gt;', 'text-domain' ) ),
                        'add_args'     => false,
                        'add_fragment' => '',
                    ) );
                ?>
            </div>
            <?php else : ?>
                <h1>No posts were found.</h1> 
            <?php endif; ?>
        </main><!-- #main -->
    </div><!-- #primary -->
</div><!-- .wrap -->
<?php get_footer(); ?>

Note: I created a new query with WP_Query in tag.php. The reason why I did this is because I didn't know how to generate the type of pagination I needed (<Prev 1 2 3 Next> style) via paginate_links(), with the main query.

Theme functions.php CODE:

<?php
    function myCustomThemeScriptEnqueue() {
        // Theme stylesheet, js
        wp_enqueue_style('myCustomTheme-style', get_stylesheet_uri(), array(), '1.0.0', 'all');
    }

    function myCustomThemeThemeSetup() {
        add_theme_support('menus');
        add_post_type_support( 'page', 'excerpt' );
    }

    function nllTagFilter($query) {
        if ($query->is_main_query()) {
            if ($query->is_tag) {
                $post_types = get_post_types();
                $query->set('post_type', $post_types);
            }
        }
    }

    add_action('pre_get_posts','nllTagFilter');

    add_action('wp_enqueue_scripts', 'myCustomThemeScriptEnqueue');
    add_action('init', 'myCustomThemeThemeSetup');

    add_theme_support( 'post-thumbnails' );
    set_post_thumbnail_size( 150, 150 );
?>

This is my theme's file-structure so far:

Share Improve this question edited Jun 15, 2020 at 8:21 CommunityBot 1 asked Jul 4, 2018 at 2:31 Cristian CCristian C 235 bronze badges 6
  • 1 what is the code of tag.php? – Michael Commented Jul 4, 2018 at 4:15
  • When you say I display all posts with that specific tag via a WP_Query, do you mean you are creating a new query in the template and not using the default main query? – Milo Commented Jul 4, 2018 at 4:41
  • How do you know index.php template file is being loaded? Use the plugin What the file to check if it is indeed index.php. It's possible that what you are thinking as content from index.php is actually from other template parts. Also, nllTagFilter function doesn't change default template loading behavior, it only includes all post types (even custom post types) with the same tag. So either some other CODE from functions.php or a plugin is changing this. Try disabling all plugins, or update your question with the CODE of functions.php. – Fayaz Commented Jul 4, 2018 at 5:33
  • @Michael Please see my edit; added the full code in both tag.php and functions.php Thanks! – Cristian C Commented Jul 4, 2018 at 5:56
  • @Milo Thank is correct. It does seem like an ugly way of doing it but I didn't know how to display the type of pagination I needed (<Prev 1 2 3 Next>) via paginate_links, without a WP_Query. (also please check my udated post; added full code from both tag.php and functions.php) – Cristian C Commented Jul 4, 2018 at 6:02
 |  Show 1 more comment

2 Answers 2

Reset to default 1

Overall CODE issues:

Your CODE is so wrong in so many ways that I shouldn't even attempt to address them here. I suggest you study Official WordPress Theme Handbook properly before doing these sort of customizations.

For the sake of the context, I'm ignoring other issues within your CODE and touching only the issues below:

1. Why index.php template is being loaded?

First of all, you are getting wrong pagination from your erroneous CODE (check the explanation below). So apart from the first tag page, all the other tag pages are nonexistent (i.e. you need to add more posts to the tag to get more tag pages).

Secondly, According to WordPress Template loading rules, 404.php template should be loaded for those non-existing tag pages (as you probably know, in HTTP, 404 is the Page Not Found Error CODE). However, since you don't have a 404.php template in your theme, index.php template is being loaded, as it is the ultimate fallback template in a WordPress theme.

Now, if you create a 404.php template, then you'll see that it'll be loaded instead of index.php for those non-existing tag pages.

Study WordPress Template Hierarchy properly for a better understanding of how different templates are loaded for different content.

2. Fixing the wrong pagination:

As I said above, you're getting nonexistent tag page numbers within your pagination. To remove those nonexistent page numbers from the pagination, you need to delete the

'total' => $post_query->max_num_pages

line from the paginate_links function call in tag.php template file.

The reason is:

  1. $post_query is your custom query, not the main query that should determine the number of pages the tag archive has. You even used wp_reset_postdata() before paginate_links function call, so no reason to use that variable here.

  2. The total parameter of the paginate_links function by default gets the value of the main WP_Query's max_num_pages property. So deleting it will automatically provide the correct value for the pagination from the main WP_Query object.

3. Pagination without new WP_Query:

In the comments you said:

The reason why I did this is because I didn't know how to generate the type of pagination I needed (<Prev 1 2 3 Next> style) via paginate_links(), with the main query.

Well, you don't need a completely new WP_Query just for a different pagination style. In fact, the paginate_links() function don't need the main WP_Query object at all!

So all you need for your desired pagination style is:

echo paginate_links( array(
    'end_size'     => 2,
    'mid_size'     => 1,
    'prev_text'    => __( '&lt;&lt; Previous page', 'text-domain' ),
    'next_text'    => __( 'Next page &gt;&gt;', 'text-domain' ) 
) );

All the other values are being collected by default (including the main WP_Query object)! So you can remove your new WP_Query object in the tag.php template entirely. Check the paginate_links documentation.

Having said that, there can be only one more thing you may want (judging from your comments):

4. Control the number of posts per tag page:

You don't need a new WP_Query for this either. This can be easily achieved from the following CODE in functions.php:

function tag_post_per_page_filter( $query ) { 
    if ( $query->is_main_query() ) { 
        if ( $query->is_tag ) { 
            $query->set( 'posts_per_page', 3 );
        }   
    }   
}   

add_action('pre_get_posts','tag_post_per_page_filter');

Basically it sets the posts_per_page to 3 in the main WP_Query object for the tag pages. That's all.

One thing to add, in case it's helpful to others: If you pass the 'total' argument, it will display more pages than necessary. :

$args = array('total'=>20);

On the blog top page (index.php), I had limited the display to 20 pages tops (this client has hundreds of articles). 5 was too little - wanted to make sure Google picks up more than that.

However, when i copied this to tag.php or category.php to achieve exactly what the OP wanted to achieve, I left those variables in by default. I figured even if i set the max to 20, it would show less if there's less articles, right? Wrong.

It turns out that if I ask for 20 pages displayed, even if there's 5 pages worth of articles under a certain category, it just overrides that.

When I hit page 6 within a specific category, it would display the contents of my 404.php because there was no more than 25 articles under a certain category (5 per page is the display limit).

I assumed: "Oh it must be loading the pagination count for ALL articles on the blog, not just this category!" I went in a wild goose chase looking for answers on how I can limit this function to show the current category pages only.

Fayaz's words above gave me the hint I needed:

Well, you don't need a completely new WP_Query just for a different pagination style. In fact, the paginate_links() function don't need the main WP_Query object at all! Commenting out the 'total' array key did the trick.

<?php
            $pages_args = array(
                'prev_next'=>false,
                // 'total'=>20
            );

            $pagelinks = paginate_links($pages_args);
            echo $pagelinks;
            ?>
发布评论

评论列表(0)

  1. 暂无评论