I created simple custom WordPress plugin for a client in 2016 that simply displays a paginated list of results queried from a custom table.
try {
$recordcountquery = 'SELECT
FName,LName
FROM
tblBurialRegister WHERE';
if (!empty($_SESSION['firstname']))
{
$cond = $mydb->prepare(' FName = %s', $_SESSION['firstname']);
$recordcountquery .= $cond;
}
if (!empty($_SESSION['lastname']) && !empty($_SESSION['firstname']))
{
$recordcountquery .= ' and';
}
if (!empty($_SESSION['lastname']))
{
$cond = $mydb->prepare(' LName = %s', $_SESSION['lastname']);
$recordcountquery .= $cond;
}
$countresults = $mydb->get_results($recordcountquery);
$total = count($countresults);
// How many items to list per page
$limit = 20;
// How many pages will there be
$pages = ceil($total / $limit);
// What page are we currently on?
$page = get_query_var('page');
if($page == 0)
{
$page = 1;
}
// Calculate the offset for the query
$offset = ($page - 1) * $limit;
// Some information to display to the user
$start = $offset + 1;
$end = min(($offset + $limit), $total);
// The "back" link
$prevlink = ($page > 1) ? '<a href="?page=1" title="First page">«</a> <a href="?page=' . ($page - 1) . '" title="Previous page">‹</a>' : '<span class="disabled">«</span> <span class="disabled">‹</span>';
// The "forward" link
$nextlink = ($page < $pages) ? '<a href="?page=' . ($page + 1) . '" title="Next page">›</a> <a href="?page=' . $pages . '" title="Last page">»</a>' : '<span class="disabled">›</span> <span class="disabled">»</span>';
if (count($countresults) > 0)
{
echo "<span id='results' class='top-offset'></span><p style='font-size:x-large;'>Showing results for: ".$_SESSION['firstname']." ".$_SESSION['lastname']."</p><br/>";
// Display the paging information
echo '<div id="paging" class="paging-text" style="font-size: large;"><p>', $prevlink, ' Page ', $page, ' of ', $pages, ' pages, displaying ', $start, '-', $end, ' of ', $total, ' results ', $nextlink, ' </p></div>';
}
$query = 'SELECT
ID,NUM,FName,LName,AGE,DATEBORN,DDate
FROM
tblBurialRegister WHERE';
if (!empty($_SESSION['firstname']))
{
$cond = $mydb->prepare(' FName = %s', $_SESSION['firstname']);
$query .= $cond;
}
if (!empty($_SESSION['lastname']) && !empty($_SESSION['firstname']))
{
$query .= ' and';
}
if (!empty($_SESSION['lastname']))
{
$cond = $mydb->prepare(' LName = %s', $_SESSION['lastname']);
$query .= $cond;
}
$query .= ' ORDER BY
LName,FName
LIMIT '
. $limit .
' OFFSET '
. $offset .'';
$results = $mydb->get_results($query);
// Do we have any results?
if (count($results) > 0) {
echo "<div style='overflow-x:auto;'><table style='font-size:large;'><th>First Name</th><th>Last Name</th><th>AGE</th><th></th>";
foreach ($results as $obj) :
$age = $obj->AGE;
if(empty($age))
{
$age = 'Unknown';
}
$bdate = $obj->DATEBORN;
if(empty($bdate))
{
$bdate = 'Unknown';
}
$ddate = $obj->DDate;
if(empty($ddate))
{
$ddate = 'Unknown';
}
echo "<tr><td>".$obj->FName."</td><td>".$obj->LName."</td><td>".$age."</td><td><form method='post' action='/'><button id='myBtn' class='et_pb_contact_submit et_pb_button rsButton' style='color: #424892!important;
border-color: #424892;' type='submit' name='RecordDetails' value=".$obj->ID.">Details</button></form></td></tr>";
endforeach;
echo "</table></div>";
} else {
echo '<p>No results found.</p>';
}
} catch (Exception $e) {
echo '<p>', $e->getMessage(), '</p>';
}
This code has not been touched since it's release and has been working. They reported to me in the last few months that the pagination is not working and user's cannot get past the first page.
It looks to me like the query string is now being removed when a link in the pagination is clicked ie. ?page=2
. Perhaps something changed in a WordPress update at some point that changed the behavior of query strings?
I looked into wp_removable_query_args()
in functions.php
which exists in the plugin like so:
function wp_removable_query_args() {
$removable_query_args = array(
'activate',
'activated',
'admin_email_remind_later',
'approved',
'core-major-auto-updates-saved',
'deactivate',
'delete_count',
'deleted',
'disabled',
'doing_wp_cron',
'enabled',
'error',
'hotkeys_highlight_first',
'hotkeys_highlight_last',
'ids',
'locked',
'message',
'same',
'saved',
'settings-updated',
'skipped',
'spammed',
'trashed',
'unspammed',
'untrashed',
'update',
'updated',
'wp-post-new-reload',
);
But my understanding is that this only removes the query strings listed, so page
should not be removed. Any help or direction would be appreciated.
I created simple custom WordPress plugin for a client in 2016 that simply displays a paginated list of results queried from a custom table.
try {
$recordcountquery = 'SELECT
FName,LName
FROM
tblBurialRegister WHERE';
if (!empty($_SESSION['firstname']))
{
$cond = $mydb->prepare(' FName = %s', $_SESSION['firstname']);
$recordcountquery .= $cond;
}
if (!empty($_SESSION['lastname']) && !empty($_SESSION['firstname']))
{
$recordcountquery .= ' and';
}
if (!empty($_SESSION['lastname']))
{
$cond = $mydb->prepare(' LName = %s', $_SESSION['lastname']);
$recordcountquery .= $cond;
}
$countresults = $mydb->get_results($recordcountquery);
$total = count($countresults);
// How many items to list per page
$limit = 20;
// How many pages will there be
$pages = ceil($total / $limit);
// What page are we currently on?
$page = get_query_var('page');
if($page == 0)
{
$page = 1;
}
// Calculate the offset for the query
$offset = ($page - 1) * $limit;
// Some information to display to the user
$start = $offset + 1;
$end = min(($offset + $limit), $total);
// The "back" link
$prevlink = ($page > 1) ? '<a href="?page=1" title="First page">«</a> <a href="?page=' . ($page - 1) . '" title="Previous page">‹</a>' : '<span class="disabled">«</span> <span class="disabled">‹</span>';
// The "forward" link
$nextlink = ($page < $pages) ? '<a href="?page=' . ($page + 1) . '" title="Next page">›</a> <a href="?page=' . $pages . '" title="Last page">»</a>' : '<span class="disabled">›</span> <span class="disabled">»</span>';
if (count($countresults) > 0)
{
echo "<span id='results' class='top-offset'></span><p style='font-size:x-large;'>Showing results for: ".$_SESSION['firstname']." ".$_SESSION['lastname']."</p><br/>";
// Display the paging information
echo '<div id="paging" class="paging-text" style="font-size: large;"><p>', $prevlink, ' Page ', $page, ' of ', $pages, ' pages, displaying ', $start, '-', $end, ' of ', $total, ' results ', $nextlink, ' </p></div>';
}
$query = 'SELECT
ID,NUM,FName,LName,AGE,DATEBORN,DDate
FROM
tblBurialRegister WHERE';
if (!empty($_SESSION['firstname']))
{
$cond = $mydb->prepare(' FName = %s', $_SESSION['firstname']);
$query .= $cond;
}
if (!empty($_SESSION['lastname']) && !empty($_SESSION['firstname']))
{
$query .= ' and';
}
if (!empty($_SESSION['lastname']))
{
$cond = $mydb->prepare(' LName = %s', $_SESSION['lastname']);
$query .= $cond;
}
$query .= ' ORDER BY
LName,FName
LIMIT '
. $limit .
' OFFSET '
. $offset .'';
$results = $mydb->get_results($query);
// Do we have any results?
if (count($results) > 0) {
echo "<div style='overflow-x:auto;'><table style='font-size:large;'><th>First Name</th><th>Last Name</th><th>AGE</th><th></th>";
foreach ($results as $obj) :
$age = $obj->AGE;
if(empty($age))
{
$age = 'Unknown';
}
$bdate = $obj->DATEBORN;
if(empty($bdate))
{
$bdate = 'Unknown';
}
$ddate = $obj->DDate;
if(empty($ddate))
{
$ddate = 'Unknown';
}
echo "<tr><td>".$obj->FName."</td><td>".$obj->LName."</td><td>".$age."</td><td><form method='post' action='http://www.website/record-search-details/'><button id='myBtn' class='et_pb_contact_submit et_pb_button rsButton' style='color: #424892!important;
border-color: #424892;' type='submit' name='RecordDetails' value=".$obj->ID.">Details</button></form></td></tr>";
endforeach;
echo "</table></div>";
} else {
echo '<p>No results found.</p>';
}
} catch (Exception $e) {
echo '<p>', $e->getMessage(), '</p>';
}
This code has not been touched since it's release and has been working. They reported to me in the last few months that the pagination is not working and user's cannot get past the first page.
It looks to me like the query string is now being removed when a link in the pagination is clicked ie. ?page=2
. Perhaps something changed in a WordPress update at some point that changed the behavior of query strings?
I looked into wp_removable_query_args()
in functions.php
which exists in the plugin like so:
function wp_removable_query_args() {
$removable_query_args = array(
'activate',
'activated',
'admin_email_remind_later',
'approved',
'core-major-auto-updates-saved',
'deactivate',
'delete_count',
'deleted',
'disabled',
'doing_wp_cron',
'enabled',
'error',
'hotkeys_highlight_first',
'hotkeys_highlight_last',
'ids',
'locked',
'message',
'same',
'saved',
'settings-updated',
'skipped',
'spammed',
'trashed',
'unspammed',
'untrashed',
'update',
'updated',
'wp-post-new-reload',
);
But my understanding is that this only removes the query strings listed, so page
should not be removed. Any help or direction would be appreciated.
1 Answer
Reset to default 2I don't believe this is an issue with a WP update, but rather an issue that has always been there but unnoticed:
$page = get_query_var('page');
page
is a query var, yet it's being reused. As a result, when you ask for page 2, you are not asking for page 2 of the custom results, that's just a coincidence.
Instead you are asking for page 2 of the main query, the main post loop that loaded the page and template. But there is no page 2.
This regularly happens to people who don't know how to modify the main query and create replacement post loops. Their custom post loops have a page 3, but the main query does not, so page 3 gives them a 404.
Since this is a custom SQL query, the fix is easy, don't reuse reserved keywords such as page
from the main query/URL for custom queries.