0

I searched a lot on this but I can't figure out why my code is not working.

I published a page with slug "blog" that uses a custom built template "page-blog.php" that I build from editing the original "page.php". I want to loop latest posts, with pagination.

For numbered pagination I tried several plugins. They all works on archive and category pages, but on page-blog.php I always get the same result. Any page I try to view gives me a 404 error. Only the loop on first page is working.

URLS are like this:

www.mywebsite.com/blog/ (page url, with first page loop, ok)

www.mywebsite.com/blog/page/2/ (404 error)

www.mywebsite.com/blog/page/3/ (404 error)

This is My page-blog.php full code.

    <?php get_header(); ?>

    <div id="primary" class="content-area col three-fourth two-columns-right">
        <main id="main" class="site-main" role="main">
            
            <?php while ( have_posts() ) : the_post(); // page loop ?>

            <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
                <header class="entry-header">
                    <?php the_title( '<h1 class="entry-title">', '</h1>' ); ?>
                    <?php edit_post_link( __( 'Edit', 'mywebsite' ), '<span class="edit-link">', '</span>' ); ?>
                </header>

                <div class="entry-content">
                    <?php the_content(); ?>
                </div>
            </article>

            <?php endwhile; // end of the page loop. ?>
            <?php wp_reset_postdata(); ?>
            
            <?php 
            // Begin secondary loop (pagination not working)
            $paged = ( get_query_var('page') ) ? get_query_var('page') : 1;
            
            $args = array (
                'post_type'              => 'post',
                'post_status'            => 'publish',
                'paged' => $paged,
            );

            // The Query
            $news_query = new WP_Query( $args );
            
            // Preserving main query
            $temp_query = $wp_query;
            $wp_query   = NULL;
            $wp_query   = $news_query;
            
            ?>
            <?php if ( $news_query->have_posts() ) : ?>
                <?php while ( $news_query->have_posts() ) : $news_query->the_post(); ?>
                    <?php get_template_part( 'content', get_post_format() );?>
                <?php endwhile; ?>

                <?php  if(function_exists('wp_paginate')) {
                    wp_paginate();
                } ?>
                
                <?php wp_reset_postdata(); ?>

            <?php else : ?>

                <?php get_template_part( 'content', 'none' ); ?>

            <?php endif; ?>
            <?php 
            // Reset main query object
            $wp_query = NULL;
            $wp_query = $temp_query;    
            ?>

        </main><!-- #main -->
    </div><!-- #primary -->

<?php get_sidebar('blog'); ?>
<?php get_footer(); ?>
2
  • 2
    Is there a reason you haven't used the built in mechanism for designating a page as the posts page under Settings > Reading?
    – Milo
    Commented Jun 7, 2014 at 19:35
  • because if I set that page as the "posts page" in setting->reading, this page becomes my homepage!
    – bluantinoo
    Commented Jun 9, 2014 at 10:42

3 Answers 3

2

MOST IMPORTANT EDIT

When I tested your code, I always added the page header name, and never realized that this was one thing that you didn't add. You should always name a custom page template so that wordpress knows it's a page template. So you need to edit your custom page template and add the header as follows

<?php
/**
 * Template Name: Name of your template
 */
get_header(); ?>

ORIGINAL ANSWER

You have to take a look at the pagination parameters of WP_Query.

  • paged (int) - number of page. Show the posts that would normally show up just on page X when using the "Older Entries" link.

  • page (int) - number of page for a static front page. Show the posts that would normally show up just on page X of a Static Front Page.

If you set this page template as a home page, your code works and paginate as it should. However, if you use this page template as a post/blog page, you will need to change

$paged = ( get_query_var('page') ) ? get_query_var('page') : 1;

to

$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;

One point of note, the plugin you are using (WP Paginate) hasn't been updated in more that two years. Although it still works, I would recommend that you have a look at other plugins that are up to date to avoid issues later.

Alternatively, you can use this function for pagination. Who the original author is, I'm not sure, but whoever you are my friend, credit goes to you.

The following code goes into functions.php

if ( ! function_exists( 'pietergoosen_pagination' ) ) :

    function pietergoosen_pagination($pages = '', $range = 2) {   
       $showitems = ($range * 2)+1;  

      global $paged;
      if(empty($paged)) $paged = 1;

          if($pages == '')
          {
             global $wp_query;
             $pages = $wp_query->max_num_pages;
                if(!$pages)
                {
                $pages = 1;
                }
            }   

           if(1 != $pages)
          {
            $string = _x( 'Page %1$s of %2$s' , '%1$s = current page, %2$s = all pages' , 'pietergoosen' );
            echo "<div class='pagination'><span>" . sprintf( $string, $paged, $pages ) . "</span>";
              if($paged > 2 && $paged > $range+1 && $showitems < $pages) echo "<a href='".get_pagenum_link(1)."'>" . __( '&laquo; First', 'pietergoosen' ) . "</a>";
             if($paged > 1 && $showitems < $pages) echo "<a href='".get_pagenum_link($paged - 1)."'>" . __( '&lsaquo; Previous', 'pietergoosen' ) . "</a>";

                for ($i=1; $i <= $pages; $i++)
                {
                   if (1 != $pages &&( !($i >= $paged+$range+1 || $i <= $paged-$range-1) || $pages <= $showitems ))
                   {
                        echo ($paged == $i)? "<span class=\"current\">".$i."</span>":"<a href='".get_pagenum_link($i)."' class=\"inactive\">".$i."</a>";
                   }
               }

               if ($paged < $pages && $showitems < $pages) echo "<a href='" . get_pagenum_link($paged + 1)."'>" . __( 'Next &rsaquo;', 'pietergoosen' ) . "</a>";
               if ($paged < $pages-1 &&  $paged+$range-1 < $pages && $showitems < $pages) echo "<a href='".get_pagenum_link($pages)."'>" . __( 'Last &raquo;', 'pietergoosen' ) . "</a>";
               echo "</div>\n";
         }
        } //  pietergoosen_pagination

endif;

You can just call the pagination in your template as follows

 <?php  pietergoosen_pagination(); ?>

EDIT

As far as I can gather from your comment to the other answer

i don't want that page to be my homepage. I have another template for my homepage. I just want it to work and list posts under the www.mywebsite.com/blog/ URL

you have set your blog page as a "Posts page:" in "Reading Settings" and some other page a your "Front page:". If this is the case, then index.php will be used as your posts page, and not your custom page template.

There is a quick way to check which template is used by the page you are viewing. Just paste the following code in your functions.php (taken from here)

add_action('wp_head', 'show_template');
function show_template() {
    global $template;
    print_r($template);
} 

EDIT 2

Here is one of my modified templates. Please test it and see it works. If this doesn't work, then I don't know. Have tested your template in as many ways as possible thinkable, and I can't get it to fail as you describe

<?php
/**
 * Template Name: Test Page 3
 */
get_header(); ?>

<div id="main-content" class="main-content">

    <div id="primary" class="content-area">
        <div id="content" class="site-content" role="main">

        <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
            <header class="entry-header">
                <?php the_title( '<h1 class="entry-title">', '</h1>' ); ?>
                <?php edit_post_link( __( 'Edit', 'mywebsite' ), '<span class="edit-link">', '</span>' ); ?>
            </header>

            <div class="entry-content">
                <?php the_content(); ?>
            </div>
        </article>


            <?php 
                global $post;

                $tmp_post = $post;

                 $paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;

                $args = array (
                    'post_type'              => 'post',
                    'post_status'            => 'publish',
                    'paged' => $paged,
                );


                    $wp_query= null;
                    $wp_query = new WP_Query();
                    $wp_query->query( $args );

        if ( $wp_query->have_posts() ) :

                while ( $wp_query->have_posts() ) : $wp_query->the_post();


                    get_template_part( 'content', get_post_format() );

            endwhile;

                if(function_exists('wp_paginate')) {
                wp_paginate();
            }   

                else 

                    get_template_part( 'content', 'none' );

                endif; 

                $post = $tmp_post; 

                 if ( comments_open() || get_comments_number() ) {
                        comments_template();
                    } ?>

    </div><!-- #content -->
    </div><!-- #primary -->

    <?php get_sidebar(); ?>

</div><!-- #main-content -->

<?php
get_footer();
12
  • Hi Pieter, thanks for help. But actually your hint does not solve the issue. Both "page" and "paged" variables gives me a 404 when visiting "blog" page paginatino links. You're right that if I set the page as homepage it works.
    – bluantinoo
    Commented Jun 9, 2014 at 10:04
  • I did try it on my side with the plugin and my custom pagination code and all seems fine. Maybe you must have a look at your permalinks Commented Jun 9, 2014 at 10:09
  • using your pagination, or anyother plugin does not change the result: 404 on pages different than the 1st one. Permalinks should work as the pagination works everywhere else in the website! I only have problems on this very page
    – bluantinoo
    Commented Jun 9, 2014 at 10:41
  • I've copied your code to my test site again, and I cannot replicate your problem. The only thing I can think of is that you have set the "Posts page" to your blog page in "Reading Settings" in which case index.php will be used and not your custom page template Commented Jun 9, 2014 at 14:41
  • That's weird. even next_posts_link() previous_posts_link() gives 404 on that page. (I did not assign the Posts page in settings). Thank you Pieter anyway
    – bluantinoo
    Commented Jun 9, 2014 at 14:49
1

From my point of view you are trying to make a pagination on a page, which can also mean wordpress is trashing your page/paged var, this can be easily solved by adding a filter adding a custom vars page/paged

add_filter('query_vars', function( $vars ){
    //!!SUPER IMPORTANT!! - always *APPEND* $vars array (NOT re-assign)
    $vars[] = 'page';
    $vars[] = 'paged';

    //!!SUPER IMPORTANT!! - always return $vars
    return $vars;
});

YOU MUST REFRESH REWRITE RULES THEN ! - easiest way is to go to your admin>preferences>permalinks => and just click on Save (changes)

If you are still getting 404, you might want to add your custom rewrite rule - after every change always refresh rewrite rules as mentionted before...

2
  • Thanks for this, it helped me somewhat, I can now get to page 2 of my custom page template using a custom query loop. Before /page/2 and ?paged=2 would both 404 but now ?paged=2 is not 404ing and I can see the expected page 2 results so I can work with this, thanks!
    – Someone
    Commented Jul 2, 2021 at 15:31
  • @Sam Yep that is usually the use case and why I've created this code.
    – jave.web
    Commented Jul 7, 2021 at 19:06
0

Have you set the blog page in reading as post page, if yes then please make a template with name home and put the above code in your home template.

hope this help you.

4
  • Hi sultan, actually i don't want that page to be my homepage. I have another template for my homepage. I just want it to work and list posts under the www.mywebsite.com/blog/ URL
    – bluantinoo
    Commented Jun 9, 2014 at 10:06
  • so you have already there a template fro home page?
    – sultan
    Commented Jun 10, 2014 at 10:39
  • hi, if you have template with homepage what ever its dont effect your homepage template will be there. just assign your homepage template to your homepage. and then crate a template with name blog but save this file with a name home.php and it will be the template for your blog page. if you have save your homepage template as home.php please change that to any other name still your homepage will be okay. When you set your page in reading setting as post page wordpress search first for index.php you can also copy your blog template on your index.php then if home.php file exit it goes for that
    – sultan
    Commented Jun 10, 2014 at 11:03
  • and assign that home.php to your blog post. now you have two option 1. to create a home.php file 2. copy your blog template to your index.php. Apart from it pagination never work for a normal template. until you have assign it in reading to post page. hope this work for you
    – sultan
    Commented Jun 10, 2014 at 11:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.