CodeIgniter pagination configuration file seems pointless

In the CodeIgniter documentation:

Simply create a new file called `pagination.php`, add the `$config` array in that file. Then save the file in `application/config/pagination.php` and it will be used automatically. You will NOT need to use `$this->pagination->initialize()` if you save your preferences in a config file.

However, one of the pagination configurations is the `base_url`, which presumably is going to be unique in every instance of pagination. For instance, if you use pagination for a controller function named `yesterday` your `base_url` might be something like `/news/yesterday/pages/`. Then for a controller function named `today`, your `base_url` might be `/news/today/pages/`. Given this scenario, you’ll need settings common for both instances stored in your `pagination.php` file and unique settings declared at the time you create the pagination links.

Consider this code:

$config['base_url'] = '/news/yesterday/pages/';   // <- unique to this instance
$config['uri_segment'] = 4;   // <- depends on above setting

$this->load->library('pagination');
$this->pagination->initialize($config); 
$data['pagination'] = $this->pagination->create_links();

In older versions of CodeIgniter, this code worked in conjunction with a `pagination.php` config file. However, after upgrading my project to version 3.1.0, I discovered the styling of my pagination links were totally broken. The settings contained within `pagination.php` were suddenly being ignored. Apparently the `initialize()` function is resetting pagination to its defaults, disregarding the `pagination.php` file entirely, and only using the `$config` settings array passed into it.

I no longer see the use of having a `pagination.php` file for common settings. If one of the core principals of CodeIgniter is DRY (Do not Repeat Yourself), then `pagination.php` has been rendered useless in this regard. You’re going to have both common configuration settings for all pagination instances in your project along with settings that are unique to each instance. If having unique settings for multiple instances precludes being able to use `pagination.php`, then its own purpose is already defeated. In order to use `pagination.php`, every instance of pagination would need an identical URL structure, which makes it impossible to use on more than one Controller function.

Consider two scenarios that illustrate the issue:

1. Do not use `pagination.php` file – Declare all settings for each instance of pagination by constructing the `$config` array in every Controller function. Settings common to all instances of pagination will need to be repeated for each instance of pagination throughout your Controller functions. Does not adhere to DRY principles. Not ideal.

2. Use `pagination.php` file – All pagination settings are contained in a central location adhering to DRY principles. However, since `base_url` is also a pagination setting, you’ll be forced to use the same Base URL for all instances of pagination. Impossible.

Workaround:

1. Copy your common pagination settings into your custom configuration file contained within `application/config/` directory. If you don’t already have a custom configuration file, create and auto-load it. Assign the array to a single configuration item named `pagination`:

// pagination
$config['pagination']	= [
    'attributes'            => array('class' => 'page'),
    'full_tag_open'         => '<p class="pagination">',
    'full_tag_close'        => '</p>',
    'cur_tag_open'          => '&nbsp;<span class="page page-current">',
    'cur_tag_close'         => '</span>',
    'first_link'            => '&laquo;',
    'last_link'             => '&raquo;',
    'next_link'             => '&rsaquo;',
    'prev_link'             => '&lsaquo;',
    'num_links'             => 6,
    'use_page_numbers'      => TRUE,
    'per_page'              => 16,	// number of items per page
];

2. Access these common settings within your Controller by calling your new custom configuration item. Use a `foreach` to loop through the `pagination` settings array:

foreach ($this->config->item('pagination') as $key => $value)
{
    $config[$key] = $value;
}
$config['base_url'] = '/news/yesterday/pages/';   // <- unique to this instance
$config['uri_segment'] = 4;   // <- depends on above setting

$this->load->library('pagination');
$this->pagination->initialize($config); 
$data['pagination'] = $this->pagination->create_links();

One advantage of this method is that you can individually over-ride any specific setting by simply assigning it to the `$config` array anytime after your `foreach` loop.

foreach ($this->config->item('pagination') as $key => $value)
{
    $config[$key] = $value;
}
$config['first_link'] = '&larr;'; // <- overrides your custom setting
$config['base_url'] = '/news/yesterday/pages/';   // <- unique to this instance
$config['uri_segment'] = 4;   // <- depends on above setting

3. Delete the seemingly useless `pagination.php` file!

WordPress turning “next” into “previous”

One of my favorite WordPress themes is Twenty Thirteen and I’ve been using it as the parent of my child themes lately. However, on my most recent project, Illinois Doberman Rescue Plus, I discovered a weird little thing with how this theme’s archive pagination function is operating. (Also true for this website‘s theme. However, I’m keeping it here as my post sorting is always chronological descending.)

No matter how you sort your postings, when you get to the bottom of the page, the link that is supposed to take you to the next page of posts is labeled “Older posts”, it’s in the lower-left corner and pointing towards the left (just like the browser’s “back” button). This only makes sense for one narrow case, when the newest post is at the top of page 1. (Even then I could argue that the link to next page of results should not be displayed like a “back” button.)

← Older posts

So for cases when the sorting is different depending on the type of archive page, let’s simply change the “Older posts” and “Newer posts” labels to something more generic… but to what? Hmm, how about “Next page” and “Previous page”? Yes, that makes sense. Err wait, the link pointing to the next page (page 2) is down in the lower-left corner and pointing to the left (just like our browser’s “back” button). This is getting goofy… a link called “Next page” but it’s pointing backwards.

← Next page

I suppose we could redesign all the templates and re-work the CSS but I think we need to take a closer peek at the workings of the `twentythirteen_paging_nav()` function which is located in Twenty Thirteen’s `functions.php` file. This function is called by the various archive template files to automatically create these pagination links as needed. Ignore the “older/newer” labels for now.

<div class="nav-links">

    <?php if ( get_next_posts_link() ) : ?>
        <div class="nav-previous">
            <?php next_posts_link( __( '<span class="meta-nav">&larr;</span> Older posts', 'twentythirteen' ) ); ?>
        </div>
    <?php endif; ?>

    <?php if ( get_previous_posts_link() ) : ?>
        <div class="nav-next">
            <?php previous_posts_link( __( 'Newer posts <span class="meta-nav">&rarr;</span>', 'twentythirteen' ) ); ?>
        </div>
    <?php endif; ?>

</div><!-- .nav-links -->

Did you catch that? They’ve place the `next_posts_link()` function inside of a `div` with the `nav-previous` class. And conversely, the `previous_posts_link()` function is contained within the `nav-next` class. This certainly explains a lot.

In defense of Twenty Thirteen, the context of the newest post being on top, the “next” page would be “older” posts. In this theme, the link to the “next” page is labeled “Older posts” and it’s pointing to the left signifying “back”. I call it “goofy” because it will break when posts are sorted in any other fashion. When oldest posts are on top or when they’re sorted alphabetically, etc., the “older” label is rendered totally meaningless. Since it, technically, always goes to the next page of the results query, it should be labeled as “next” and indeed the `next_posts_link()` function is how it’s created. However, simply re-labeling it as “next” is not good enough as it’s in the lower-left corner and pointing backwards towards the left.

My fix is simple. I copied this entire function into my child theme’s `functions.php` file. Since the original is wrapped inside `if ( ! function_exists( ‘twentythirteen_paging_nav’ ) )`, the version in the child theme will take precedence. Then I rearranged the function a bit…

<div class="nav-links">

    <?php if ( get_next_posts_link() ) : ?>
        <div class="nav-next">
            <?php next_posts_link( __( 'Next page <span class="meta-nav">→</span>', 'twentythirteen' ) ); ?>
        </div>
    <?php endif; ?>

    <?php if ( get_previous_posts_link() ) : ?>
        <div class="nav-previous">
            <?php previous_posts_link( __( '<span class="meta-nav">←</span> Previous page', 'twentythirteen' ) ); ?>
        </div>
    <?php endif; ?>

</div><!-- .nav-links -->

Now using this slightly modified version, I get a “Next page” link that always points to the right and it always goes to the next page in the results. The link in the lower-left corner is labeled as “Previous page” and always goes to the previous page in the results. This is the most logical way as that it breaks all dependance on the sorting order.

                                               Next page →

As you can see my proposed arrangement perfectly corresponds to more traditional numbered pagination with “previous” on the left and “next” on the right…

← Prev      1  2  3  4  5  6  7  8      Next →

You’ll still need to adjust your CSS a bit as Twenty Thirteen makes the “previous” link in the lower-left corner (formally called “Older posts”) about 60% larger than its mate. I think their idea was to make the button going to the next page larger. Since their positions and labels are flipped, you must adjust the CSS sizes.

Since you’re over-riding the parent theme, you’ll need to over-ride everything dealing with spacing and size. The following is the bare minimum required in the child theme to flip the sizes to correspond with our previous changes.

.paging-navigation .nav-previous {
	padding: 13px 0;
}
.paging-navigation .nav-next {
	padding: 0;
}
.paging-navigation .nav-previous .meta-nav {
	padding: 3px 0 8px;
	width: 50px;
}
.paging-navigation .nav-next .meta-nav {
	padding: 17px 0 23px;
	width: 80px;
}