PHP OOP Pagination - php

I'm having an issue with pagination. I've debugged as mush as I can and it seems there is an issue with the SELECT query and execution. If I take out the pagination part the query executes and displays all entries in a long table. I tried executing an array, bindValue and bindParam but nothing works, can anyone see what I'm missing?
function showEmployees() {
$count = $this->dbh->query("SELECT * FROM employee_info");
$count->rowCount();
$count = $count->rowCount();
// if ($count > 0) {
// echo "The total amount of employees is " . $count;
// } else {
// echo "There are no records in this table.";
// }
$page_rows = 10;
$last_page = ceil($count / $page_rows);
echo $last_page;
if ($last_page < 1) {
$last_page = 1;
}
$page_num = 10;
if (isset($_GET['pn'])) {
$page_num = preg_replace('#[^0-9]#', '', $_GET['pn']);
}
if ($page_num < 1) {
$page_num = 1;
} elseif ($page_num > $last_page) {
$page_num = $last_page;
}
$limit = 'LIMIT ' .($page_num -1) * $page_rows .', '. $page_rows;
$query = $this->dbh->prepare("SELECT * FROM employee_info ORDER BY employee_id DESC :page_limit");
$query->bindParam(':page_limit', $limit );
$query->execute();
$t = "<table name='displayEmployees' border='1' >";
$t .="<tr>";
$t .= "<th>Employee ID</th>";
$t .= "<th>First Name</th>";
$t .= "<th>Last Name</th>";
$t .= "</tr>";
while($u = $query->fetch(PDO::FETCH_ASSOC)) {
$t .="<tr>";
$t .= "<td>{$u['employee_id']}</td>";
$t .= "<td>{$u['first_name']}</td>";
$t .= "<td>{$u['last_name']}</td>";
$t .="</tr>";
}
$t .="</table>";
return $t;
}

It think it's the way you handled the limit although that should have tripped an error.
Try:
$beginLimit = ($page_num-1)*$page_rows;
$endLimit = $page_rows;
$query = $this->dbh->prepare("SELECT * FROM employee_info ORDER BY employee_id DESC LIMIT :begin,:end");
$query->bindValue(':begin',(int)$beginLimit,PDO::PARAM_INT);
$query->bindValue(':end',(int)$endLimit,PDO::PARAM_INT);
$query->execute();

You can't include keywords as parameters to your prepared statements. You'll need to do this:
$limit = 'LIMIT ' .($page_num -1) * $page_rows .', '. $page_rows;
$query = "SELECT * FROM employee_info ORDER BY employee_id DESC ".$limit;
$query->query($query);
Note: because the parameters are already sanitised by your script you can trust them, so the benefit of a prepared statement is largely lost in this case.

Related

PHP/SQL - pagination for fuzzy search results

I have created a search function for the products on my site and I tried to put in pagination so that it is not just a big long list of results. So I started off with something like this:
**Note: I just replaced $_GET['search_term'] with 'whatever' just for this example, and where I have var_dump() I have a function that displays the products for each id in the array it is given.
$term = 'whatever'; //$_GET['search_term'];
$new_term = '%'.$term.'%';
if(isset($_GET['page'])){
$page = $_GET['page'];
}else{
$page = 1;
}
$per_page = 20;
$last_page = ceil($resultCount/$per_page);
if($page<1){
$page = 1;
}else if($page>$last_page){
$page = $last_page;
}
$pagination = "";
$limit = "LIMIT ".($page-1)*$per_page.",".$per_page;
if($last_page!=1){
if($page!=1){
$prev = $page-1;
$pagination .= "<a class='pagination' href='store'><<</a>";
$pagination .= "<a class='pagination' href='store/$prev'><</a>";
}
for($i=$page-2; $i<=$page+2; $i++){
if($i>0 && $i<=$last_page){
if($i == $page){
$pagination .= "<a class='pagination selected'>$i</a>";
}else{
$pagination .= "<a class='pagination' href='store/$i'>$i</a>";
}
}
}
if($page!=$last_page){
$next = $page+1;
$pagination .= "<a class='pagination' href='store/$next'>></a>";
$pagination .= "<a class='pagination' href='store/$last_page'>>></a>";
}
}
if(isset($term)){
echo $pagination;
$ids = [];
$params = [$new_term];
$sql = "SELECT * FROM products WHERE name LIKE ? $limit";
$stmt = DB::run($sql,$params);
$resultCount = $stmt->rowCount();
if($resultCount > 0){
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$id = $row["pro_id"];
$params3 = [$id];
$sql3 = "SELECT * FROM products WHERE id=?";
$stmt3 = DB::run($sql3,$params3);
while($row = $stmt3->fetch(PDO::FETCH_ASSOC)){
$id = $row["id"];
array_push($ids,$id);
}
}
var_dump($ids);
}
echo $pagination;
}
This worked fine, but then I wanted to make it a fuzzy search so I did:
$term = 'whatever'; //$_GET['search_term'];
$new_term = '%'.$term.'%';
$params = [$new_term];
$sql = "SELECT * FROM products WHERE name LIKE ?";
$stmt = DB::run($sql,$params);
$resultCount = $stmt->rowCount();
if($resultCount < 1){
$sql = "SELECT * FROM products";
$stmt = DB::run($sql);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$id = $row["pro_id"];
$result = $row[$lang];
similar_text($term,$result,$similarity);
$similar_array[$similarity][] = $id;
}
$closest_match = array_keys($similar_array);
rsort($closest_match);
$match_count = count($closest_match);
$similar_ids = [];
for($i=0; $i<$match_count; $i++){
foreach($similar_array[$closest_match[$i]] as $id){
array_push($similar_ids,$id);
}
}
$resultCount = count($similar_ids);
}
if(isset($_GET['page'])){
$page = $_GET['page'];
}else{
$page = 1;
}
$per_page = 20;
$last_page = ceil($resultCount/$per_page);
if($page<1){
$page = 1;
}else if($page>$last_page){
$page = $last_page;
}
$pagination = "";
$limit = "LIMIT ".($page-1)*$per_page.",".$per_page;
if($last_page!=1){
if($page!=1){
$prev = $page-1;
$pagination .= "<a class='pagination' href='store'><<</a>";
$pagination .= "<a class='pagination' href='store/$prev'><</a>";
}
for($i=$page-2; $i<=$page+2; $i++){
if($i>0 && $i<=$last_page){
if($i == $page){
$pagination .= "<a class='pagination selected'>$i</a>";
}else{
$pagination .= "<a class='pagination' href='store/$i'>$i</a>";
}
}
}
if($page!=$last_page){
$next = $page+1;
$pagination .= "<a class='pagination' href='store/$next'>></a>";
$pagination .= "<a class='pagination' href='store/$last_page'>>></a>";
}
}
if(isset($term)){
echo $pagination;
$ids = [];
$params = [$new_term];
$sql = "SELECT * FROM products WHERE name LIKE ? $limit";
$stmt = DB::run($sql,$params);
$resultCount = $stmt->rowCount();
if($resultCount > 0){
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$id = $row["pro_id"];
$params3 = [$id];
$sql3 = "SELECT * FROM products WHERE id=?";
$stmt3 = DB::run($sql3,$params3);
while($row = $stmt3->fetch(PDO::FETCH_ASSOC)){
$id = $row["id"];
array_push($ids,$id);
}
}
var_dump($ids);
}else{
var_dump($similar_ids);
}
echo $pagination;
}
There was probably a much better way of doing this but this is what I have. My question then is how can I get the pagination to work here for the fuzzy results ($similar_ids)? I was thinking of some sort of function that will splice the array depending on the page number but I am not sure how I would go about this.
This does not answer your question, but I'm going to say these anyway:
Looking closely, you have a possible sql injection bug in handling of $limit.
Also, using a search index like Apache Solr or ElasticSearch would give you pagination nearly for free anyway. You might want to look into that. Setting up a dedicated index is another can of worms, yes, but then you would also have more and better options to handle that fuzzy search part too.

Detect Previous Next ID

I have a little script that have a Previous & Next button.
My problem is I want to detect & place the ID in those buttons
this is the code from the pagination
<body>
<?php include_once 'data.php'; ?>
<center>
<ul class="pagination">
<?php
if($page_counter == 0){
echo "<li><a href=?start='0' class='active'>0</a></li>";
for($j=1; $j < $paginations; $j++) {
echo "";
}
}else{
echo "<a href=?start=$previous><button>Previous</button></a>";
for($j=0; $j < $paginations; $j++) {
if($j == $page_counter) {
echo " ";
}else{
echo " ";
}
}if($j != $page_counter+1)
echo "<a href=?start=$next><button>Next</button></a>";
}
?>
</ul>
</center>
In this part I have the ID but the problem is I can`t get it with this example to place it into the pagination.
<?php
foreach($result as $row) {
echo '
<div class="card"><button1>
'. $row['notice_id'] .'
<div class="time-left">
<div class="dropdown1">
' ;
}
}
else {
echo '';
}
$conn->close();
?>
</div></div>
This is the code from data.php I think I need to place some code into for detection from the ID
<?php
//include configuration file
require 'configuration.php';
$start = 0; $per_page = 1;
$page_counter = 0;
$next = $page_counter + 1;
$previous = $page_counter - 1;
if(isset($_GET['start'])){
$start = $_GET['start'];
$page_counter = $_GET['start'];
$start = $start * $per_page;
$next = $page_counter + 1;
$previous = $page_counter - 1;
}
// query to get messages from messages table
$q = "SELECT * FROM group_notice LIMIT $start, $per_page";
$query = $db->prepare($q);
$query->execute();
if($query->rowCount() > 0){
$result = $query->fetchAll(PDO::FETCH_ASSOC);
}
// count total number of rows in students table
$count_query = "SELECT * FROM group_notice";
$query = $db->prepare($count_query);
$query->execute();
$count = $query->rowCount();
// calculate the pagination number by dividing total number of rows with per page.
$paginations = ceil($count / $per_page);
?>
You can use some formulas for calculate limit and offset of results.
For example you have 100 records, and you want to paginate it into 10 records per page, and the formula is like below.
// Get Page from Query String
$page = 1;
if(!empty($_GET["page"])){
$page = $_GET["page"];
}
// Get record count
$count_query = "SELECT * FROM group_notice";
$query = $db->prepare($count_query);
$query->execute();
$count = $query->rowCount();
$per_page = 10; // records per page
$pages = ceil($count/$per_page); // get total page
$start = $page * $per_page - $per_page; // get offset
// Do something with your records
$query = db->prepare("SELECT * FROM group_notice LIMIT ?, ?");
$query->bind_param("ii", $start, $per_page); // you should use bind param if you use prepared statement
$query->execute();
if($query->rowCount() > 0){
$result = $query->fetchAll(PDO::FETCH_ASSOC);
}
if($page > 1){
echo 'Prev'; // Print Prev Page
}
for($i = 1; $i <= $pages){
echo ''.$i.''; // Print Page Number
}
if($page < $pages){
echo 'Next'; // Print Next Page
}
Hope it helps.

Error in pagination code

I am doing pagination for the first time and run into a problem. The problem appears to be on the line where I have while with mysqli_fetch_array. Error says this: mysqli_fetch_array() expects parameter 1 to be mysqli_result, boolean given...
Here is my code with the whole pagination part. Thanks!
if (!(isset($page_num))) {
$page_num = 1;
}
$sqlko = mysqli_query($con, "SELECT * FROM clanek INNER JOIN uzivatel ON clanek.uzivatel_ID=uzivatel.uzivatel_ID");
$rows = mysqli_num_rows($sqlko);
$rows_num = 5;
$last = ceil ($rows/$rows_num);
if($page_num < 1) {
$page_num = 1;
} else if($page_num > $last) {
$page_num = $last;
}
$max = 'limit ' .($page_num - 1) * $rows_num .',' .$rows_num;
$vytah = mysqli_query($con,"SELECT * FROM clanek INNER JOIN uzivatel ON clanek.uzivatel_ID=uzivatel.uzivatel_ID $max ORDER BY clanek_ID DESC ");
while($clanecky = mysqli_fetch_array($vytah)){
if($clanecky["typ_ID"] == "1") {
$nadpis_alpha = $clanecky["nadpis"];
$nadpis = urldecode($nadpis_alpha);
$obsah = $clanecky["obsah"];
$uzivatel_ID = $clanecky["uzivatel_ID"];
$jmeno = $clanecky["jmeno"];
$prijmeni = $clanecky["prijmeni"];
$datum = $clanecky["datum"];
$novinka_ID = $clanecky["clanek_ID"];
echo "<div class='domu_column'>";
echo "<h2><a href='index.php?page=novinka&id=$novinka_ID&nazev=$nadpis'>".$nadpis."</a></h2>";
echo "<div id='novinka_panel'><b>".$jmeno." ".$prijmeni."</b> | ";
echo $datum."</div>";
echo "<p>".$obsah."</p>";
echo "Stránka $page_num z $last";
if ($page_num == 1) {
} else {
echo " <a href='{$_SERVER['PHP_SELF']}?page=domu&page_num=1'> <<-First</a>";
echo " ";
$predchozi = $page_num - 1;
echo " <a href='{$_SERVER['PHP_SELF']}?page=domu&page_num=$predchozi'> <<-Předchozí</a>";
}
echo "----";
if ($page_num == $last) {
} else {
$next = $page_num + 1;
echo " <a href='{$_SERVER['PHP_SELF']}?page=domu&page_num=$next'>Next -></a> ";
echo " ";
echo " <a href='{$_SERVER['PHP_SELF']}?page=domu&page_num=$last'>Last ->></a> ";
}
echo "</div>";
}}
LIMIT (variable $max) must be last in SQL-query. However, you inserted before ORDER BY. See SELECT Syntax.
$max = 'limit ' .($page_num - 1) * $rows_num .',' .$rows_num;
$vytah = mysqli_query($con,"SELECT * FROM clanek INNER JOIN uzivatel ON clanek.uzivatel_ID=uzivatel.uzivatel_ID $max ORDER BY clanek_ID DESC ");
Change to:
$vytah = mysqli_query($con,"SELECT * FROM clanek INNER JOIN uzivatel ON clanek.uzivatel_ID=uzivatel.uzivatel_ID ORDER BY clanek_ID DESC $max ");

Pagination not displaying PHP PDO

Im trying to paginate my query only nothing is being outputted, can anybody see where im going wrong? Im very new to PHP/PDO
else {
try
{
$per_page = '3';
$result = $conn->prepare("SELECT * FROM directory WHERE user_active != ''");
$rows = $result ->fetchAll();
$total_records = count($rows);
$pages = ceil($total_records / $per_page);
$page = (isset ($_GET['page'])) ? (int) $_GET['page'] : 1 ;
$start = ($page - 1) * $per_page;
$query = $conn->prepare("SELECT * FROM directory WHERE user_active != ''");
while($row = $query->fetch(PDO::FETCH_ASSOC)){
echo '<br>' . $row['id'] . '<br>' . $row['First_Name'] . '<br>' . $row['Surname'] . '<br>';
} ?>
<br><br>
<?php
if ($pages >= 1 && $page <= $pages){
//if ($page>1 && $page <= $pages){$previous=($page -1); echo 'Previous';}
for($x=1; $x<=$pages; $x++){ echo ($x == $page) ? ' <strong>'.$x.'</strong> ' : ' '.$x.' ';}
//if ($page>1 && $page <= $pages){ $next=($page+1) ; echo 'Next';}
}
####################### Close Database #######################
$db = NULL;
}
catch(PDOException $e)
{
print 'Exception : '.$e->getMessage();
}
};
You never execute the query.
$result->execute();
$rows = $result ->fetchAll();
$query->execute();
while($row = $query->fetch(PDO::FETCH_ASSOC)){
Also it's better to use LIMIT in your query. Something like that:
//to get need page
$per_page = 3;
$page = (isset ($_GET['page'])) ? (int) $_GET['page'] : 1 ;
$result = $conn->prepare(
"SELECT * FROM directory
WHERE user_active != ''
LIMIT ".(($page - 1) * $per_page).", ".$per_page
);
$result->execute();
$rows = $result ->fetchAll();
//to get count of pages
$result = $conn->prepare(
"SELECT COUNT(*) FROM directory
WHERE user_active != ''"
);
$result->execute();
$total-pages = reset($result->fetch(PDO::FETCH_NUM));

PHP paging, viewing a certain page first

This is my script for the paging on my site when the user clicks on a league.
The league is then echoed to the screen, and if the league is over 3 rows then it splits it up in to several pages.
What I am doing after is depending on where the user is in the league (the SQL query is using ORDER BY the total points column in the table), e.g if the user is on page one of the league table then for it to display that page first, but if the user is on page 3 of the league table then for that page to displayed first.
Does anyone know a way in order for me to achieve this?
//Recently updated from answer
$sql="SELECT members.username, members.total_points FROM members, members_leagues WHERE members.username = members_leagues.username AND
members_leagues.sub_league = '$chosenleague' ORDER BY members.total_points DESC";
$result=mysql_query($sql);
$i = 0;
$found = false;
$team_position = 0;
while (!$found && $row = mysql_fetch_row($result)){
if ($row[username] == $_SESSION[username]) {
$team_position = $i;
$found = true;
}
$i++;
}
$rowsPerPage = 3;
$pageNum = ceil($i/$rowsPerPage);
//end of recently updated
if(isset($_GET['page']))
$pageNum = $_GET['page'];
$offset = ($pageNum - 1) * $rowsPerPage;
$counter = $offset + 1;
$query = " SELECT members.username, members.teamname, members.total_points, FROM members, members_leagues WHERE members.username = members_leagues.username AND members_leagues.sub_league = '$chosenleague' ORDER BY members.total_points DESC " . " LIMIT $offset, $rowsPerPage";
$result = mysql_query($query) or die('Error, query failed');
echo "<h3 style=\"color:red;\">$chosenleague</h3>";
echo "<table>";
echo "<tr><th>Position</th>";
echo "<th>Team</th>";
echo "<th>Points/Overall</th>";
echo "<th>Points/Last Race</th>";
echo "<th>Team Setup</th></tr>";
while($row = mysql_fetch_array($result))
{
if($row[username] == $_SESSION[username])
echo "<tr style=\"color:red;\"><td>";
else
echo "<tr><td>";
echo $counter;
echo "</td><td>";
echo $row[teamname];
echo "</td><td>";
echo $row[total_points];
echo "</td><td>";
echo "</td><td>";
echo "</td></tr>";
$counter++;
}
echo "</table>";
$query = "SELECT COUNT(members.username) AS numrows FROM members, members_leagues WHERE members.username = members_leagues.username
AND members_leagues.sub_league = '$chosenleague'";
$result = mysql_query($query) or die('Error, query failed');
$row = mysql_fetch_array($result, MYSQL_ASSOC);
$numrows = $row['numrows'];
$maxPage = ceil($numrows/$rowsPerPage);
$self = $_SERVER['PHP_SELF'];
$nav = '';
if ($pageNum > 1)
{
$page = $pageNum - 1;
$prev = " << Prev ";
$first = " First ";
}
else
{
$prev = '';
$first = '';
}
if ($pageNum < $maxPage)
{
$page = $pageNum + 1;
$next = " Next >> ";
$last = " Last ";
}
else
{
$next = '';
$last = '';
}
echo "<div id=\"pagenum\">Page $pageNum of $maxPage ". $first . $last . $prev . $next ."</div>";
You can do it via mysql or php:
With PHP:
Found the position of the requested record in the array, then calculate the page you have to extract and execute the corresponding query. Something like.
$i = 0;
$found = false;
$team_position = 0;
while (!$found && $row = mysql_fetch_row) {
if ($row['team'] == 'team_your_searching_for') {
$team_position = $i;
$found = true;
}
$i++;
}
//calculate $top and $bottom
...
$sql = "SELECT * FROM members LIMIT $top, $bottom;";
...
With MySQL:
You can create a query that generates an autoincrement value and another that selects from the other's result. I mean
-- get the the selected member's position
SELECT team, pos FROM (SELECT team, points, #position = #position + 1 AS pos FROM members ORDER BY points) WHERE team = #the_team_your_searching_for;
-- get the nr of members
SELECT COUNT(*) FROM members;
...
-- calculate the page you wanna extract (#top, #bottom), and extract it
SELECT * FROM members LIMIT #top, #bottom;

Categories