Jonnie Grieve Digital Media: Blog

Home
by on 17th February, 2023 - 12:19pm (0)

Blog: Starting a new design for my blog – Part 5 (More Posts)

The 5th in this series of my blog where I walk through my process and thoughts of making a WordPress theme in preparation for making a new design for my blog.

  • I started by making a new plan and created the template files needed for a new WordPress theme.
    The WordPress Loop gets all the content from WordPress Posts, or Pages depending on the page template used and displays all its contents.
  • In the second part, I explain how to bring content dynamically into your posts and pages with the Loop.
  • In part 3 I wrote about how I created and styled a single.php template.
  • In part 4, I focused on the secondary content area where I put together a series of the most common WordPress widgets.

In this part, I’ll walk readers through the process of using pagination methods to group together related pages of posts.

First, let’s tidy up the styling a bit more.

I added a few extra style rules to .entry and .pagination which centralizes the individual post and pagination elements. The margin values add some separation for each individual blog entry.

.entry {
    padding: 10px 5px;
    width: 95%;
    margin: 10px auto;
}
.pagination {

    width: 95%;
    padding: 10px 5px;
}

Preparing to paginate content

There are a few things I want to say about how I prepared to paginate the posts list. WordPress only shows 10 posts per page by default. I set the admin reading setting “Blog pages show at most” to 8 posts which constrained the listing to fewer posts rather than a list of the entire contents, which was over 100 on a single page.

When I started out, I began to realise I may have to be flexible in my approach to the pagination links I created which means trying not to be constrained by what I’d prototyped in my markup.

I rewrote the loop to make it easier to find a place to put the pagination links, by separating out the if and while blocks of the loop.

<?php if ( $main_blog->have_posts() ):  ?>

    <!-- Pagination -->
    <?php while ( $main_blog->have_posts() ) : $main_blog->the_post(); ?>
        ....
    <?php endwhile; ?>
    <?php else: ?>
    <p>No content</p>
<?php endif; ?>

Pagination methods

With the loop refactored, I’m ready to start introducing pagination methods to the template files. There are several of these methods which do slightly different things.

Multiple Posts Pagination

  • posts_nav_link()
  • next_posts_link()
  • previous_posts_link()
  • get_next_posts_link()
  • get_previous_posts_link()
  • paginate_links()
  • the_posts_pagination()
  • get_the_posts_pagination()

Single Post pagination

With all of the above in place, I was able to verify that the above functions worked, and I was able to see the links for core WordPress posts that are created.

The functions work as they are and they don’t need to be echoed.

<?php
previous_posts_link(); 
next_posts_link();

Let’s look at what each of these pagination methods gives you.

posts_nav_link()

<?php posts_nav_link();

This method outputs either the strings “<<Previous Page” or “Next Page >>” depending on the place in the pagination. It’ll link to the relevant page in the pagination group. It does not accept a string argument.

<a href="http://localhost/jgdm_blog/page/2/">Next Page »</a>
<a href="http://localhost/jgdm_blog/">« Previous Page</a>

There are 2 other pagination functions that do the same thing.

Next and Previous posts()

<?php

previous_posts_link();
next_posts_link();

These 2 methods do accept string arguments, and with them, you can customise the text according to your needs.

previous_posts_link( "Back" );
next_posts_link( "Forward" );

Here’s an example taken from the WordPress Developer Handbook.

<!-- Start the pagination functions before the loop. -->

<div class="nav-previous alignleft"><?php next_posts_link( 'Older posts' ); ?></div>
<div class="nav-next alignright"><?php previous_posts_link( 'Newer posts' ); ?></div>

the_posts_pagination()

This method is used to generate a more robust set of pagination links. The markup it generates is as follows.

<nav class="navigation pagination" aria-label="Posts">
    <h2 class="screen-reader-text">Posts navigation</h2>
    <div class="nav-links">
        <a class="prev page-numbers" href="http://localhost/jgdm_blog/">Previous</a>
        <a class="page-numbers" href="http://localhost/jgdm_blog/">3</a>
        <span aria-current="page" class="page-numbers current">4</span>
        <a class="page-numbers" href="http://localhost/jgdm_blog/">5</a>         
        <a class="next page-numbers" href="http://localhost/jgdm_blog/">Next</a>
    </div>
</nav>

The first thing to note is that it uses the same class as the HTML element that I used when I first created the template, which has the effect of using the background colour for the method and the HTML element – keeping my design intact.

The .prev and .next classes are the links that actually move between the available pages in the list of posts. The .page-numbers class can be used to style the colour of the links. Although it’s best in my opinion to use a selector like

nav-links a {} 

to do this. This would remove any conflicts with using the .current class to style the colour of the page number that the user is on.

Aside from that, it means I can base my original styling on the pagination container class, but the markup has a few layers to it. But if we want to use the_posts_pagination() method we have to do away with any pagination links coded in the HTML or find a way to adapt it.

paged queries

In my installation, the pagination methods were only showing 2 pages when I knew I had far more posts stored in the database. The reason this was happening was that the pagination methods get the number of links it needs from WordPress Core Posts but not for Custom Post Types (CPT).

WordPress needs a way to track which part of the pagination it is in at any given time. This is where something called the paged parameter comes into play. That’s fine for Core Post Types but there needs to be a fix for CPTs. And that fix is found in this post in the WordPress stack exchange. – Link

This is the line used by PHP to help WordPress determine what the current page is supposed to be.

<?php $custom_query_args['paged'] = (get_query_var('paged')) ? get_query_var('paged') : 1;

Now I’ll set up a custom query in the usual way, so first by specifying the post name argument in an Array of arguments and then by defining the WP_Query object,

<?php

    $args = array(

        'post_type' => 'blog_posts',
        //'paged' => $paged        
);

$main_blog = new WP_Query( $args );

We now need to force WordPress to show pagination links for our custom query by backing up the main query object and saving this to our custom query variable. The following code does this by separating from the main query object and then saving it back to the custom query variable.

$temp_query = $wp_query;
$wp_query = NULL;
$wp_query = $main_blog;

Now add the pagination links into your design according to your needs.

<?php the_posts_pagination(); ?>

Run the WordPress Loop in order to generate the list of posts.

<?php if ( have_posts() ): ?> 

    <!-- Pagination --> 

<?php while ( have_posts() ) : the_post(); ?>
    <div class = "entry">

    <h3> <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a> </h3>
    <p> <?php echo the_excerpt(); ?> </p>

    <p> <?php echo the_content(); ?> </p>

    <p> <?php echo the_field( "article_blurb" ) . "..."; ?> </p>

</div>
<?php endwhile; ?> 

<?php else: ?> 

    <p>No content</p>

<?php endif; ?> 

Once pagination functions have been output, reset the main query object.

<?php
   // Reset the posts data 
   wp_reset_postdata(); 
?>

Reset main query object

<?php
    $wp_query = NULL;
    $wp_query = $temp_query; ?>

With the pagination in place, we need to pay attention to some styling again. I mentioned before that because the posts pagination method uses a .pagination class it means it takes on the style of the container element fairly seamlessly.  The div element with the class of nav-links is next in the document tree and I can use a selector to style the element that stores the number of the current page to the colour black to differentiate it from the other pagination links.

.nav-links {

    .current {

        color: black;
        font-size: 15px;
        font-weight: bold;
        padding: 10px 0px;
        padding: 0;
        margin-left: 0;
    }
}

I left a padding value of zero on the page-numbers class to make sure all the numbers in the pagination element stayed vertically aligned with each other.  I also added a selector for the pagination dots that WordPress adds for brevity and spacing  (we don’t want to see every pagination link every time).

.nav-links {   
    . . . 
    .page-numbers {

        padding: 0;
    }

    .dots {

        color: #555555;
        font-size: 18pt;
    }
}

Links

The Pagination URLs are a little hard to get the noggin around in terms of how they work.  Core posts and post types seem to work alongside each other in a strange way.  Let me work through a use case to illustrate what I mean.

Below I’ve added some links to the main navigation in header.php. One is a link to the Post Type homepage page (home.php) and the other link is to the Posts Page for the “Blog Posts” CPT.

<header>

    <h1>JGDM Blog</h1>
    <nav class="navigation">
        <li><a href="http://localhost/jgdm_blog/">Posts</a></li>
        <li><a href="http://localhost/jgdm_blog/blog_posts/2/page/1/">Blog Posts</a></li>
        . . .
    </nav>

I can use the “Posts” link to access the list of WordPress core posts – http://localhost/jgdm_blog/
(assume “localhost” could be any web domain)

I also link to the “Blog Posts” CPT in the second link. http://localhost/jgdm_blog/blog_posts/2/page/1/.

The URL structure for the second link  is less than ideal. Custom post type that uses an unusual URL system in order to work correctly. Having “blog_posts” in the URL is fine because you need a way to differentiate between CPT posts from the Core Posts type but the pagination will not work unless I include an extra integer after it.

e.g. http://localhost/jgdm_blog/blog_posts/2/page/1/.

Additionally, if I was to use something like http://localhost/jgdm_blog/blog_posts/1/page/5/  the URL will redirect to one of the single blog post pages. e.g. http://localhost/jgdm_blog/blog_posts/100daysofcode-r6d38/

The Pagination WordPress Post Type (served by the home.php template) works flawlessly. http://localhost/jgdm_blog/page/2/

Conclusion

I now have a theme set up to paginate through WordPress Core Posts and one custom post type.  They use index.php and home.php to do this.   It’s not an absolutely perfect solution by any means in terms of the URLs used but they are functional and use the right amount of pagination in each case.  I also have an archive-blog_post.php template set up for my custom post type which can’t be accessed right but that is designed to be an archive template specifically for that post type.

So with some caveats, this part of WordPress theme development is done. Next, I’ll talk about using Archive, Category and functionality for single-page templates.

This post has been assigned to the following categories

    Leave a Reply

    Your email address will not be published. Required fields are marked *