Reputation: 67
I'm trying to use pagination for a customer table using PHP, MySQL & Bootstrap. I wrote this code:
<div class="container mx-auto">
<!--Add class table-responsive for responsive table -->
<table class="table mx-auto">
<thead>
<tr>
<th>Name</th>
<th>Surname</th>
<th>Email</th>
<th>Phone</th>
<th>Address</th>
<th>Zipcode</th>
<th>City</th>
<th>Company</th>
</tr>
</thead>
<tbody>
<ul class="pagination">
<?php
if(isset($_GET['page'])){
$previous = $_GET['page'] - 1;
if($previous = -1 ){
$previous = 0;
}
if($previous = 0){
echo '<li class="page-item"><a class="page-link" href="#">Previous</a></li>';
}
else{
echo '<li class="page-item"><a class="page-link" href="?page='. $previous.'">Previous</a></li>';
}
}
$page_max = 10;
$entriesInDatabase = $database->getData("SELECT count(id) FROM customers");
$numberOfPages = ceil($entriesInDatabase['count(id)']/$page_max);
for($i = 0; $i < $numberOfPages; $i++){
echo '<li class="page-item"><a class="page-link" href="?page='. $i . '">'. $i. '</a></li>';
}
if(isset($_GET['page'])) {
$page = $_GET['page'];
$start = $page * 10;
$end = ($page + 1) * 10;
var_dump($start);
var_dump($end);
}
else{
$page = 0;
$start = $page * 10;
$end = 10;
}
$customers = $database->getUsers("SELECT * FROM customers LIMIT $start, $end");
?>
<li class="page-item"><a class="page-link" href="#">Next</a></li>
</ul>
<?php
foreach($customers as $customer){
$name = $customer ['name'];
$surname = $customer['surname'];
$email = $customer['email'];
$phone = $customer['phone'];
$address = $customer['address'];
$zipcode = $customer['zipcode'];
$city = $customer['city'];
$company = $customer['company'];
$id = $customer['id'];
echo "<tr>
<td>$name</td>
<td>$surname</td>
<td>$email</td>
<td>$phone</td>
<td>$address</td>
<td>$zipcode</td>
<td>$city</td>
<td>$company</td>
</tr>";
}
?>
I want each page to show 10 records from the database so giving a limit to my SQL query. What happends now is the following; page 0 shows 10 records, page 1 shows 20 records, page 2 shows also 20 records but page 9 shows 11 records.
Could anyone help me out fixing this issue?
Upvotes: 3
Views: 1980
Reputation: 5395
You'd be better off thinking about the principles of how it works rather than just looking at the code.
Firstly, you need to know:
COUNT()
You then need to understand how LIMIT
works. If you do something such as LIMIT 50, 10
it means use 50
as the starting point ("from the 51st record in the table" - remember the indexes start at 0
) and get the next 10
rows. The latter number, 10
, is the number of rows you want to show per page.
In terms of constructing the links the easiest method is to make the ?page=
parameter in the URL the first value for the LIMIT
query because this changes per page (e.g. 50
in the example above), where as you know the other number (10
) is constant. You can produce these links by doing a ceil
on the number of records in the table, divided by the number of records per page. This will output the appropriate numbers for the URL.
Let's say you had 362 records in your database and wanted to show 10 per page. This would produce the URL's:
$per_page = 10;
$records_in_db_table = 362; // You must calculate this from a COUNT() query
$n = ceil($records_in_db_table / $per_page);
for ($x=0; $x<$n; $x++) {
$page = ($x * $per_page);
echo '?page=' . $page;
}
The above code outputs:
?page=0
?page=10
?page=20
?page=30
// ...
?page=360
Then you just feed these in to your query's LIMIT
condition, e.g.
?page=10
== LIMIT 10, 10
?page=20
== LIMIT 20, 10
?page=30
== LIMIT 30, 10
It's also worth noting that you don't need to care about what happens if you're trying to LIMIT
to more records than exist. For example the last URL (?page=360
) will do LIMIT 360, 10
. There are only 362 records in your database so you might assume this won't work as there are only 2 records that could be returned from that query. However, it will just return the last 2, no problem.
Equally if you try and use a number which is way beyond the total number of records (?page=99999
which gives LIMIT 99999, 10
) it will just return an empty result set, not an error. Some people code things in to do a simple check, e.g.
if ((int)$_GET['page'] > $records_in_db_table) {
// Display error message
}
Remember that you should sanitise $_GET['page']
or at the very least cast it to an integer. Do not inject anything from $_GET
directly into your query, and use parameter binding (e.g. PDO) if possible.
You may also want to look at DataTables (https://datatables.net/) since this does a lot of what you need without writing any such code and works well with Bootstrap.
Upvotes: 2
Reputation: 13
You should ignored the page zero, and try :
start : ($page - 1) * 10;
end : $end = 10;
Upvotes: 0
Reputation: 1232
Your problem comes from the fact that you don't know how the LIMIT
keyword works.
If you only give it one parameter, it will be interpreted as the maximum number of entries from the query that must be returned.
If you pass it two values, the first will be interpreted as the start offset while the second will still be the maximum amount of returned entries.
In other words, writing LIMIT 50, 60
- which would happen in your case when preparing the 5th page - will start getting results from the 51th matching entry and will also return the 59 next ones.
If you want to display 10 records per page, hard write 10 as the second LIMIT
parameter and it should be better.
Upvotes: 2