In PHP, I'm trying to implement pagination that displays different results from a SQL database based off LIMIT. I know how to write pagination with multiple parameters but I'm unsure of how to code the application to recognize the second condition for the SQL interjection.
If you look at the code where it contains the foreach and the href containing page_number and category_id I need to get the pagination at the bottom to adhere to which category picked within the foreach to display the correct data. Also I couldn't figure out how to implement the pages without hardcoding within the for loop
This is the function for the SQL query page
function get_products_by_category($category_id, $pn)
{
global $db;
$arithmetic = 8*($pn -1);
$query = "SELECT * FROM products
WHERE products.categoryID = :category_id
ORDER BY productID LIMIT $arithmetic, 8";
$statement = $db->prepare($query);
$statement->bindValue(":category_id", $category_id);
$statement->execute();
$products = $statement->fetchAll();
$statement->closeCursor();
return $products;
}
Here's where it gets called
if ($action == 'list_products')
{
$category_id = filter_input(INPUT_GET, 'category_id',
FILTER_VALIDATE_INT);
if ($category_id == NULL || $category_id == FALSE)
{
$category_id = 1;
}
$category_name = get_category_name($category_id);
$categories = get_categories();
$products = get_products_by_category($category_id, $pn);
$products_amount = get_products_total($category_id);
$total = count($products_amount);
include('product_list.php');
}
Here's the foreach and pagination
<?php
$pn;
$current_category;
$total_page = $total/8;
$remain = $total % 8;
if($remain > 0)
{
$total_page = $total_page + 1;
}
?>
<aside>
<!-- display a list of categories -->
<h2>Categories</h2>
<nav>
<ul>
<?php foreach ($categories as $category) : ?>
<li>
<a href="?category_id=<?php echo $category['categoryID']; ?>">
<?php echo $category['categoryName'];?>
</a>
</li>
<?php endforeach; ?>
for($i = 1; $i <= $total_page; $i++)
{
?>
<?php echo $i; ?>
<?php
if($i == 1)
{
$pn = 1;
}
else if($i == 2)
{
$pn = 2;
}
else if($i == 3)
{
$pn = 3;
}
}
?>
Try this:
<?php echo $i; ?>
Related
I already created a table that has limit and it is working well with pagination
if(isset($_GET['page']) && !empty($_GET['page'])){
$currentPage = $_GET['page'];
}else{
$currentPage = 1;
}
$startFrom = ($currentPage * $showRecordPerPage) - $showRecordPerPage;
$totalEmpSQL = "SELECT * FROM producttable";
$allEmpResult = mysqli_query($conn, $totalEmpSQL);
$totalProducts = mysqli_num_rows($allEmpResult);
$lastPage = ceil($totalProducts/$showRecordPerPage);
$firstPage = 1;
$prev = $currentPage - 1;
$next = $currentPage + 1;
$sortertype = "name";
$sorterorder = "ASC";
$sort = "";
if(isset($_GET['sort'])){
$sort = $_GET['sort'];
}
if ($sort == 'nameasc') { // If you Sort it with value of your select options
$sortertype = "name";
$sorterorder = "ASC";
} elseif ($sort == 'namedesc') { // else if you do not pass any value from select option will return this
$sortertype = "name";
$sorterorder = "DESC";
}
$empSQL = "SELECT id,name, price,description
FROM `producttable` ORDER BY $sortertype $sorterorder LIMIT $startFrom, $showRecordPerPage";
$empResult = mysqli_query($conn, $empSQL);
while($row = mysqli_fetch_assoc($empResult)) {}
**for pagination
<ul class="pagination justify-content-start" >
<li class="page-item <?php if($currentPage <= 1){ echo 'disabled'; } ?>">
<a class="page-link"
href="<?php if($currentPage <= 1){ echo '#'; } else { echo "?page=" . $prev; } ?>">Prev</a>
</li>
<?php for($i = 1; $i <= $lastPage; $i++ ): ?>
<li class="page-item <?php if($currentPage == $i) {echo 'active'; } ?>">
<a class="page-link" href="inde.php?page=<?= $i; ?>"> <?= $i; ?> </a>
</li>
<?php endfor; ?>
<li class="page-item <?php if($currentPage >= $lastPage) { echo 'disabled'; } ?>">
<a class="page-link"
href="<?php if($currentPage >= $lastPage){ echo '#'; } else {echo "?page=". $next; } ?>">Next</a>
</li>
</ul>
**and also manage to create a working sorting options that displays the type of order and doesnt reset when changed
<select name="sort" id="myselect" onchange="sort(this.value);" class="py-1" >
<option value="nameasc" <?php if($sort == 'nameasc'):?> selected="selected"<?php endif;?>>Name:Asc</option>
<option value="namedesc" <?php if($sort == 'namedesc'):?> selected="selected"<?php endif;?>>Name:Desc</option>
</select>
<script type="text/javascript">
function sort(option){
window.location = window.location.pathname+'?sort='+option;
}
</script>
the only problem is that when the page goes to the next page, the sorting options resets and also the table reset to default sorting. Is there anyway to make the pagination connect to the sorting options part?
You are not reading the GET value received for the sort
$sort = $_GET['sort'];
So your code should be
$sort = $_GET['sort']; // this line is missing
if ($sort == 'nameasc') { // If you Sort it with value of your select options
$sortertype = "name";
$sorterorder = "ASC";
} elseif ($sort == 'namedesc') { // else if you do not pass any value from select option will return this
$sortertype = "name";
$sorterorder = "DESC";
}
I have the following code:
$max = 4;
$page = isset($_GET['page']) ? ($_GET['page']) : '1';
$init = $page - 1;
$init= $max * $init;
$strCount = "SELECT COUNT(*) AS 'total_mytable' FROM mytable";
$varstrCount = $crud->viewdatas($strCount);
$total = 0;
if(count($varstrCount)){
foreach ($varstrCount as $row) {
$total = $row["total_mytable"];
}
}
$result = "SELECT * FROM mytable ORDER BY id_mytable LIMIT $init,$max";
$varresult = $crud->viewdatas($result);
content of page:
<?php
if(count($varresult)){
foreach ($varresult as $res) {
?>
<h5><?php echo $res['title'] ?></h5>
<?php
}
}
?>
<?php
$max_links = 10;
$previous = $page - 1;
$next = $page + 1;
$pgs = ceil($total / $max);
if($pgs > 1 ){
if($previous > 0){
echo "<li><a href='".BASE_URL."/category/$previous' aria-label='Previous'><span aria-hidden='true'>«</span></a></li>";
} else{
}
for($i=$page-$max_links; $i <= $pgs-1; $i++) {
if ($i <= 0){
}else{
if($i != $page{
if($i == $pgs){ //if end insert 3 dots
echo "<li><a href='".BASE_URL."/category/".($i)."'>".$i."</a></li> ...";
}else{
echo "<li><a href='".BASE_URL."/category/".($i)."'>".$i."</a></li>";
}
} else{
if($i == $pgs){ //if end insert 3 dots
echo "<li>".$i."</li> ...";
}else{
echo "<li>".$i."</li>";
}
}
}
}
if($next <= $pgs){
echo "<li><a href='".BASE_URL."/category/$next' aria-label='Next'><span aria-hidden='true'>»</span></a></li>";
}else{
}
}
?>
The result:
And I not understand the reason for the active number stay right off the paging menu
In the code I defined max-links for 10, but no show number 5 and if I define max links for 3 changes nothing , displays the same result as the image.
Thanks for any help
echo "<li>".$i."</li>";
on the above line add up a href, seems like you have css formatting for li>a because of which you are not getting the required formatting on only li. so for getting better formatting for all paging links current, prev, next. you need to add up a tags.
echo "<li><a>".$i."</a></li>"; //in your else part
I have this algorithm I made for pagination.
The $array variable is a result set from the query after the page number and limit has been set. It's a result from a PDO::fetchAll() function.
The $array["totalCount"] contains the count of ALL the rows in the table, not only that set but all the rows.
What I want is to limit the number of pages displayed, and make it somehow like google style pagination, I've search a lot of similar questions online, but what makes me struggle is to guess how I can implement it in my algorithm which is much different from others.
Thanks in advance.
public static function renderPaginationBar($obj, $params) {
$array = $obj->getAll($params);
$set = $params["set"];
$perSet = $params["limit"];
$pages = ceil((int)$array["totalCount"] / (int)$perSet);
if($pages > 1 && $set <= $pages) {
$query = preg_replace('/set=\d*/i', '', http_build_query($_GET));
?>
<ul class="pagination">
<?php
if($set > 1) {
?>
<li><<< Inicio</li>
<li><<</li>
<?php
}
for($i = 1; $i <= $pages; $i++) {
$class = $set == $i ? "active" : "";
?>
<li class="<?php echo $class; ?>"><?php echo $i; ?></li>
<?php
}
if($set < $pages) {
?>
<li>>></li>
<li>Último >>></li>
<?php
}
?>
</ul>
<?php
}
unset($array["totalCount"]);
return $array;
}
you can try displaying it as a dropdown between the 'next' and 'prev' button if you want.. it would be easier to display all the page numbers..
or you can first get the value of current page, add 5 and store it as '$add' and minus 5 and store it as '$minus' then insert this in the page buttons:
<input type="submit" value="<?php echo $page_num;?>" <?php if($pagenum > $add || $pagenum < $minus){ echo "style='display:none'";?>>
it will hide the buttons that are more than 5 and less than 5 the current page
replace yor 'for' with this:
$get_add = $params["set"] + 5;
$get_minus = $params["set"] - 5;
for($i = 1; $i <= $pages; $i++) {
$class = $set == $i ? "active" : "";
?>
<li class="<?php echo $class; ?>" <?php if($i > $get_add || $i < $get_minus){ echo "style='display:none;position:absolute'";?>><?php echo $i; ?></li>
<?php
}
i have this php mysql query
<?php
$product = mysql_query('SELECT * FROM products LIMIT 6 ');
$pro = mysql_fetch_assoc($product);
?>
Now that query will return 6 products from database and what i want to do is echo 3 products inside a <div> and the other 3 products inside another <div> like this
<div class="first-3>
///Here i want to echo 3 products from the query from 1-3
<?php echo $pro['title']; ?>
</div>
<div class="second-3>
///Here i want to echo the rest 3 products of the query from 4-6
<?php echo $pro['title']; ?>
</div>
<?php
$num = 6;
$product = mysql_query('SELECT * FROM products LIMIT $num');
$firstDiv = "";
$secondDiv = "";
$i = 0;
while ($pro = mysql_fetch_assoc($product)) {
if ($i < ($num /2)) {
$firstDiv .= $pro['title'];
}
else {
$secondDiv .= $pro['title'];
}
$i++;
}
?>
And:
<div class="first-3>
<?php $firstDiv ?>
</div>
<div class="second-3>
<?php $secondDiv ?>
</div>
Iterate and output the values.
<?php
$product = mysql_query('SELECT * FROM products LIMIT 6 ');
$i = 1;
echo '<div class="first-3">';
while ( $pro = mysql_fetch_assoc($product) ) {
if ($i === 3) {
echo '</div><div class="second-3">';
}
echo $pro['title'];
$i++;
}
echo '</div>';
?>
Note that it's not safe to use mysql_query, you should be using mysqli or preferrably PDO.
mysql_fetch_assoc is used to retrieve a row in the resultset.
Doc: http://php.net/manual/es/function.mysql-fetch-assoc.php
A loop is required to iterate on each row.
A very simple example:
// Get a collection of 6 results
$products = mysql_query('SELECT * FROM products LIMIT 6 ');
// iterate over the 6 results
$i=0;
echo '<div class="first-3>';
while ($pro = mysql_fetch_assoc($products)) {
$i++;
// Print an item
echo $pro["title"];
// If 3 items are printed end first div and start second div
if($i==3){
echo '</div><div class="second-3">';
}
}
echo '</div>';
// Free the collection resources
mysql_free_result($products);
Just set up a counter to divide in groups of 3:
$count = 0;
while (...)
{
// your code
$count++;
if ( ($count % 3) === 0 )
{
echo '</div><div class="...">';
}
}
Please note that the mysql_* functions are deprecated and you should switch to PDO or mysqli.
$product = mysqli_query($conn, 'SELECT * FROM products LIMIT 6 ');
$results = array();
while($pro = mysqli_fetch_assoc($product)) {
$results[] = $pro;
}
echo '<div class="first-3">';
for($i = 0; $i < 3; $i++) {
echo $results[$i]['title'];
}
echo '</div><div class="second-3">';
for($i = 3; $i < 6; $i++) {
echo $results[$i]['title'];
}
echo '</div>';
Everytime you get the multiple of 3, ($k % 3 == 0) you will increment the flag variable, you can do then some conditions with the variable flag, i used here iterators because the hasNext() beauty.
Example
$pro = array(1, 2, 3, 4, 5, 6);
$flag = 0;
$pro = new CachingIterator(new ArrayIterator($pro));
foreach ($pro as $k => $v) {
// if multiples 3
if ($k % 3 == 0) {
$flag++;
if ($flag == 1) {
echo '<div class="first-3" style="border:1px solid black;margin-bottom:10px;">';
} else if ($flag == 2) {
echo '</div>'; // Closes the first div
echo '<div class="second-3" style="border:1px solid red">';
}else{ // if you have more than 6
echo '</div>';
}
}
// insert Data
echo $v . '<br/>';
if (!$pro->hasNext())
echo '</div>'; // if there is no more closes the div
}
I need to loop through a recordset (PHP + MySQL), grouping each 2 records in a list item
My actual code (semplified) is this:
<?php
// how many total records do I have?
mysql_select_db($database_connEIB, $connEIB);
$query_rsMediaCount = "SELECT COUNT(*) AS med_count FROM media";
$rsMediaCount = mysql_query($query_rsMediaCount, $connEIB) or die(mysql_error());
$row_rsMediaCount = mysql_fetch_assoc($rsMediaCount);
$mCount = $row_rsMediaCount['med_count']; // total records
$mPages = ceil($mCount / 2); // max LIs to create
$mIndex = 0; // useful initialization for LIMIT, see below
if ($mCount > 0) { // let's show markup only if there's some record!
?>
<ul>
<?php for ($mPage = 1; $mPage <= $mPages; $mPage++) { // create the LIs ?>
<li>
<?php
$query_rsMedia = "SELECT med_id FROM media LIMIT $mIndex, 2";
$rsMedia = mysql_query($query_rsMedia, $connEIB) or die(mysql_error());
$row_rsMedia = mysql_fetch_assoc($rsMedia);
do { ?>
<div><?php echo $row_rsMedia['med_id']; ?></div>
<?php } while ($row_rsMedia = mysql_fetch_assoc($rsMedia));
$mIndex += 2; // increment the LIMIT by 2 steps ?>
</li>
<?php } ?>
</ul>
<?php } ?>
The output is sort like this:
<ul>
<li>
<div>1</div>
<div>2</div>
</li>
<li>
<div>3</div>
<div>4</div>
</li>
<li>
<div>5</div>
</li>
</ul>
Everything works, but is there a more elegant or efficient solution?
Thanks in advance
Do only one query and group the results within the loop. Use the modulo operator %:
$query_rsMedia = "SELECT med_id FROM media";
$rsMedia = mysql_query($query_rsMedia, $connEIB) or die(mysql_error());
if (mysql_num_rows($rsMedia) > 0) { // check if there is at least one result
echo '<ul>';
$index = 0;
while ($row_rsMedia = mysql_fetch_assoc($rsMedia)) {
if ($index % 2 == 0) echo '<li>'; // open <li> bevore even result
echo '<div>'.$row_rsMedia['med_id'].'</div>';
if ($index % 2 == 1) echo '</li>'; // close <li> after odd result
$index++;
}
if ($index % 2 == 1) echo '</li>'; // close <li> if odd result count
echo '</ul>';
}
(just written, not testet)
I would try to run fewer queries.
$query_rsMedia = "SELECT med_id FROM media";
$rsMedia = mysql_query($query_rsMedia, $connEIB) or die(mysql_error());
$count = 0;
echo '<ul>';
while($row = mysql_fetch_assoc($rsMedia))
{
//check divisibility to know when to show li
if ($count % 2 == 0) {
echo '<li>';
}
echo '<div>' . $row['med_id'] . '</div>';
$count++;
if ($count % 2 == 0) {
echo '</li>';
}
}
if ($count % 2 == 1) echo '</li>';
echo '</ul>';
Ask query once without the LIMIT statement. Then do something like this:
$iteration=0;
echo '<li><ul>';
while ($row_rsMedia = mysql_fetch_assoc($rsMedia)
{
echo '<div>'.$row_rsMedia['med_id'].'</div>';
$iteration++;
if ($iteration%2==0 && $iteration<$mCount)
echo '</ul><ul>'
}
echo '</ul><li>';
I would separate the HTML and PHP for ease of reading first. Also, I am not entirely convinced of the do...while loop that actually prints the result (what if the table was empty?).
Your code also contains two distinct ideas (generating the list and getting the page count), so I would break them into two separate functions. Makes code easier top read.
It may, therefore, look like this:
<ul>
<?php generateList(); ?>
</ul>
<?php
function getPageCount() {
mysql_select_db($database_connEIB, $connEIB);
$query_rsMediaCount = "SELECT COUNT(*) AS med_count FROM media";
$rsMediaCount = mysql_query($query_rsMediaCount, $connEIB) or die(mysql_error());
$row_rsMediaCount = mysql_fetch_assoc($rsMediaCount);
$mCount = $row_rsMediaCount['med_count'];
$mPages = ceil($mCount / 2);
}
function generateList()
$mIndex = 0;
$mPages = getPageCount();
if ($mCount > 0) {
for ($mPage = 1; $mPage <= $mPages; $mPage++) {
$result = "<li>" ;
$query_rsMedia = "SELECT med_id FROM media LIMIT $mIndex, 2";
$rsMedia = mysql_query($query_rsMedia, $connEIB) or die(mysql_error());
$row_rsMedia = mysql_fetch_assoc($rsMedia);
while ((row_rsMedia = mysql_fetch_assoc($rsMedia)) != null) {
$result .= "<div>".$row_rsMedia['med_id']."</div>";
}
$mIndex += 2;
$result .= "</li>
}
echo $result;
}
?>
Hope it helps.