PHP: Pagination of an array of data

April 27, 2021

We need to do pagination when we have a large set of data, and we want to display only a specific number of records per page.

First, we would need the data in an array as shown the following code.
The data would have been retrieved from a database or an api call or any other source.


// Let's assume we have the following array of data
$data = [
    ['id' => 1, 'title' => 'Example 1'],
    ['id' => 2, 'title' => 'Example 2'],
    ['id' => 3, 'title' => 'Example 3'],
    ['id' => 4, 'title' => 'Example 4'],
    ['id' => 5, 'title' => 'Example 5'],
    
    /* ... more rows */
    
    ['id' => 1000, 'title' => 'Example 1000'],
];

Pagination Variables

As the next step we need to determine which records from the database are the ones that correspond to the page we want to show.

The page we want to show is usually received as a url parameter.

In the following code we will calculate the position of the top record of the page. Then with that "position" we will grab the records of that page.


// The page to display (Usually is received in a url parameter)
$page = intval($_GET['page']);

// The number of records to display per page
$page_size = 25;

// Calculate total number of records, and total number of pages
$total_records = count($data);
$total_pages   = ceil($total_records / $page_size);

// Validation: Page to display can not be greater than the total number of pages 
if ($page > $total_pages) {
    $page = $total_pages;
}

// Validation: Page to display can not be less than 1
if ($page < 1) {
    $page = 1;
}

// Calculate the position of the first record of the page to display
$offset = ($page - 1) * $page_size;

// Get the subset of records to be displayed from the array
$data = array_slice($data, $offset, $page_size);

Then we can display the subset of records we got with the above code.


<?php foreach ($data as $row) { ?>
    <div><?php echo $row['title']; ?></div>
<?php } ?>


Pagination Links

Now we need to display the pagination links.

There are several ways we can display the links. One basic method would be to display the links for the first, last, previous and next pages.


// variables for pagination links
$page_first = $page > 1 ? 1 : '';
$page_prev  = $page > 1 ? $page-1 : '';
$page_next  = $page < $total_pages ? $page + 1 : '';
$page_last  = $page < $total_pages ? $total_pages : '';


<a href="sample-page.php?page=<?php echo $page_first; ?>">« First</a>
<a href="sample-page.php?page=<?php echo $page_prev; ?>">Prev</a>
<a href="sample-page.php?page=<?php echo $page_next; ?>">Next</a>
<a href="sample-page.php?page=<?php echo $page_last; ?>">Last »</a>

The pagination links will look like this:



Another method to display the pagination links could be to display groups of page numbers like in the following code.


// page links
$N = min($total_pages, 9);
$pages_links = array();

$tmp = $N;
if ($tmp < $page || $page > $N) {
    $tmp = 2;
}
for ($i = 1; $i <= $tmp; $i++) {
    $pages_links[$i] = $i;
}

if ($page > $N && $page <= ($total_pages - $N + 2)) {
    for ($i = $page - 3; $i <= $page + 3; $i++) {
        if ($i > 0 && $i < $total_pages) {
            $pages_links[$i] = $i;
        }
    }
}

$tmp = $total_pages - $N + 1;
if ($tmp > $page - 2) {
    $tmp = $total_pages - 1;
}
for ($i = $tmp; $i <= $total_pages; $i++) {
    if ($i > 0) {
        $pages_links[$i] = $i;
    }
}


<?php $prev = 0; ?>
<?php foreach ($pages_links as $p) { ?>
    <?php if (($p - $prev) > 1) { ?>
        <a href="#">...</a>
    <?php } ?>
    <?php $prev = $p; ?>

    <?php
    $style_active = '';
    if ($p == $page) {
        $style_active = 'style="font-weight:bold"';
    }
    ?>

    <a <?php echo $style_active; ?> href="sample-page.php?page=<?php echo $p; ?>"><?php echo $p; ?></a>
<?php } ?>

The pagination links will look like this:

1 2 3 4 5 6 7 8 9 ... 39 40