php pagination for search result failing to display - php

i've just been learning pagination. i'm having trouble getting it to work for search results. it displays the first page correctly with the right number of links but clicking on any of the links (even on the page 1) goes to a blank page.
can somebody please tell me what i'm doing wrong:
The following code is for when the search button is clicked.
<?php
include('includes/connect-db.php');
include('includes/functions.php');
if (isset($_GET['searchbtn'])){
$product=$_GET['products'];
$status=$_GET['ticket_status'];
$order_by=$_GET['order_by'];
$ticket_type=$_GET['ticket_type'];
#check if product has been selected
if ($_GET['products'] == 'select'){
echo '<font class="error">&nbsp Please select a product to search.</font>';
}else{
if ($status == 'All' AND $order_by == 'All' AND $ticket_type == 'All' ){
$page_query="SELECT * FROM tickets WHERE product='$product' ORDER BY created DESC";
}elseif ($ticket_type == 'BOX'){
$page_query="SELECT * FROM tickets WHERE product='$product' AND status='$status' AND pbi <> '-' ORDER BY '$order_by' ";
}elseif ($ticket_type == 'PVR'){
$page_query="SELECT * FROM tickets WHERE product='$product' AND status='$status' AND inc <> '-' ORDER BY '$order_by' ";
}else{
$page_query="SELECT * FROM tickets WHERE product='$product' AND status='$status' ORDER BY created DESC";
}
}#end of else
$results_per_page=3;
$result_set=pagination($results_per_page,$page_query);
$query=$result_set['query'];
$pages=$result_set['pages'];
#SELECT, SHOW, DESCRIBE, EXPLAIN and other statements returning resultset. A resource on success or False on Error
if (!empty($query)){
$result = mysqli_query($db,$query) or die( "My query ($query) generated an error: ".mysql_error());
$num_results = mysqli_num_rows($result);
if ($num_results > 0){
displayTicket($result);
if ($pages > 1){
echo '</br>';
for($i=1;$i<=$pages;$i++){
echo ' '.$i.' ';
}
}
}else{
echo "&nbsp No Records found.";
}
}#query string is not empty
}
?>
i have put the pagination code in a separate function:
function pagination($per_page, $pages_query){
include('includes/connect-db.php');
$pagination[]=array();
#total result count
$total_result=mysqli_query($db,$pages_query);
#ceil takes a decimal number and gives the nearest whole number
$total=mysqli_num_rows($total_result);
$pages = ceil($total / $per_page);
$page = (isset($_GET['page'])) ? (int)$_GET['page'] : 1;
$start = ($page - 1) * $per_page;
$query = " LIMIT $start,$per_page";
$query = $pages_query.$query;
$pagination['query'] = $query;
$pagination['pages'] = $pages;
return $pagination;
}
Note: the pagination linking to other pages only fails when i attempt it with the search feature. i have tried it on a page that lists information in a table and the links work fine.

It looks to me like the problem is the information in the link: localhost/test/searchProductForm.php?page=1 tells searchProductForm which page to display, but it doesn't tell it what the search information was. Without that, your search page has no idea what to display. Try changing the pagination link to include all the information that was in the original search link (i.e., your products, ticket_status, order_by, and ticket_type parameters).

I know this is an old thread, but for anyone not able to solve a similar problem with the code used above, it could be to do with the lack of session_start() at the beginning of the document.
I say this because although the code is trying to obtain the session variables passed by the ?page= &products= etc to $_GET statements but they are not being retrieved into the variables from the URL but you need to place the session_start() at the begging of your PHP document to pass the information from the URL to the strings.

Related

PHP Limit rows returned by MySQL and do something if last row returned

I didn't know exactly how to word this question but by do something I mean that I would like to hide or not show my "next" button that is shown below. I have a script that pulls all the images from MySQL and prints them to my page by 30 images per page and the next 30 will create a new page that is activated by my back/next buttons. My "back" button has a if statement if $startrow isn't >= 0 than it won't show but I would like the same concept with my next button when the last row in my database is shown and it hides my next button.
I was thinking if you can detect the first empty row or the last row of the database and if so hide the next button. Otherwise it keeps adding 30 to $startrow when nothing is shown on screen.
I found a script helping me with this here but it didn't tell me how to hide the next button.
<?php
$startrow = $_GET['startrow'];
if (!isset($_GET['startrow']) or !is_numeric($_GET['startrow'])) {
$startrow = 0;
} else {
$startrow = (int)$_GET['startrow'];
}
?>
<?php
$db = mysqli_connect("localhost", "root", "", "media");
$uploaded = mysqli_query($db, "SELECT * FROM images LIMIT $startrow, 30");
while ($row = mysqli_fetch_array($uploaded)) {
echo "<div class='img_container'>";
echo "<li><img class='img_box' src='uploads/images/".$row['image_title']."' ></li>";
echo "</div>";
}
$prev = $startrow - 30;
if ($prev >= 0) {
echo '<div class="prevRow">Back</div>';
}
echo '<div class="nextRow">Next</div>';
?>
You could try something like
$num_rows = 30; // rows on a page
$db = mysqli_connect("localhost", "root", "", "media");
// get total possible rows
$res = mysqli_query($db, "SELECT count(id) FROM images");
$row = $res->fetch_row();
$total_rows = $row[0];
$res->close();
$uploaded = mysqli_query($db, "SELECT * FROM images LIMIT $startrow, $num_rows");
while ($row = mysqli_fetch_array($uploaded)) {
. . .
}
$prev = $startrow - $num_rows;
if ($prev >= 0) {
echo '<div class="prevRow">Back</div>';
}
if ( $startrow+$num_rows < $total_rows ) {
echo '<div class="nextRow">Next</div>';
}
Potentially a little faster than the answer from #RiggsFolly, you can modify your existing query to count the rows.
SELECT SQL_CALC_FOUND ROWS * FROM images LIMIT $startrow, 30
Then, after the query returns, you run a second query to get the answer:
SELECT FOUND_ROWS()
The FOUND_ROWS() function returns the number of rows the previous query would have returned, without LIMIT (or an offset).
This is probably not as fast as your original query would be in isolation, but should be slightly faster than SELECT COUNT(...) ... followed by your original query. With small data sets, though, any differences will likely be below measurable limits.
See also https://dev.mysql.com/doc/refman/5.7/en/information-functions.html
You can also combine these things into a stored procedure that accepts items per page and page number, and returns all of the records along with metadata items such as the total number of pages.

PHP/MySQLi Page Numbers and Final query issues

I am trying to create a page number function that displays 9 results per page from my forum_replies.sql table. My PHP code so far will only display page 1, page 2. Page 1 has 9 query's but page two has none... but there's 22 rows of data that should be fetched, so at least 2 pages should show!
Here's my code!
if(isset($_GET["p"]) && is_numeric($_GET["p"]) && $_GET["p"] > 1) {
$currentPage = $_GET["p"];
$limiter = $currentPage * 9;
} else {
$currentPage = 1;
$limiter = 0;
}
$finalQuery = "SELECT * FROM forum_replies WHERE thread_id = '1' ORDER BY id ASC LIMIT " . $limiter . ",9";
Figured out that the isset at the top.. $limiter works like this
0,9 = page 1.. correct
18,9 = page 3.. how do I get page 2 (9,9) and so on.. cause it's completely skipping 9,9!
How about calling echo $db->error; after each query? You can also echo the querys and try them in phpMyAdmin to find out what's wrong. I can't spot a mistake in the finalQuery, at least not syntax-wise.

How to hide the next button when no pages to dispaly

Can someone help me please? I am sure it is easy for you guys. I am battling to find a solution on how to hide the next link when there are no pages to display my code is as follows:
if (!isset($_GET['page']) or !is_numeric($_GET['page'])) {
$page = 0;
} else {
$page = (int)$_GET['page'];
}
$pages_query=mysql_query ("SELECT COUNT * FROM hardware");
$result = mysql_query("SELECT * FROM hardware LIMIT $page, 3");
echo 'Next<p>';
$prev = $page - 3;
//only print a "Previous" link if a "Next" was clicked
if ($prev >= 0) {
echo 'Previous';
}
You can use mysql_num_rows($result) to get the number of records in hardware:
$result = mysql_query("SELECT * FROM hardware LIMIT $page, 3");
$record_count = mysql_num_rows($result);
if ($record_count > 1)
echo 'Next';
in your if statement check if the $page is greater than 0 then according to the outcome of the value of $page write your code. you can use another if statement in the first if statement and make it detect the situation and decide what to do. The other thing is if the user clicked next then the user is on the second page so your previous should appear if $prev is higher than 1 it should make it
something along the lines of:
$itemsPerPage = 3;
$sql = "SELECT * FROM hardware";
$result = mysql_query($sql);
$count = mysql_num_rows($result);
$pageCount = $count/$itemsPerPage;
if($pageCount > $page) { //Are there more pages worth of items stored, than we're currently looking at?
echo 'next';
}
You want to be using OFFSET in your SQL syntax, as well as LIMIT.
LIMIT limits the number of rows returned.
OFFSET tells it to start a number of rows into the result set.
You need to limit to the number of items you want on a page. and offset by that number*page.
Hopes this helps.

Modifing Pagination-Sorting Method to Change Rows Per Page

Hi i have a PHP based Pagination and Sorting Method which works fine.
I am able to sort and paginate according to any categories, but having problems when it comes to rows per page.
i have used GET Method to fetch information for pagination and sorting as
if (isset($_GET['rpp'])&& is_numeric($_GET['rpp'])) {
$rowsperpage = mysql_real_escape_string($_GET['rpp']);
}else{
$rowsperpage='5';
}
if (isset($_GET['page']) && is_numeric($_GET['page'])) {
$currentpage = (int) mysql_real_escape_string($_GET['page']);
} else {
$currentpage = 1;
}
if (isset($_GET['order']) && in_array($_GET['order'], $order)) {
$orderby = mysql_real_escape_string($_GET['order']);
}else{
$orderby='id';
}
$sortby = '';
if (isset($_GET['sort'])) {
$sortby = mysql_real_escape_string($_GET['sort']);
}else{
$sortby='desc';
}
for pagination i have used following type of url string
echo " <li><a href='$pagename?order=$orderby&sort=$sortby&rpp=$rowsperpage&page=$nextpage'>Next»»</a>
and my mysql query is
$sql2 = "SELECT * FROM internet_security ORDER BY $orderby $sortby LIMIT $rowsperpage OFFSET $offset";
and in html i have used links to sort categories like
id-desc:
id-asc:
title-desc:
title-asc:
**limit rows by**
5
10
20
My question is
every thing is working fine except when i limit row per page via limit rows by - rows get limited to whatever limit(5,10,20) is selected but then if i click pagination every thing goes to its default set value i.e by id and in DESC order with LIMIT of 5.
and if i do it like
id-desc:
id-desc:
id-desc:
then it works but then i must have at least 12 links for full functionality.which is not a standard approach.
what i want is once a limit is set either by default or by sorting options, i shall be able to sort by id title etc.. and paginatin should works along with it.
i hope i made it clear.
please see what i am doing wrong and suggest any possible solution to my approach.
(Upgrading to an answer)
Store $rpp in a $_SESSION variable, updating only if it's present in $_GET:
if ( isset($_GET[ 'rpp'])) $_SESSION['rpp'] = intval($_GET['rpp']);
elseif (!isset($_SESSION['rpp'])) $_SESSION['rpp'] = 5;
Then use $_SESSION['rpp'] in your query:
$sql2 = "
SELECT *
FROM internet_security
ORDER BY $orderby $sortby
LIMIT $_SESSION[rpp] OFFSET $offset
";

Paginator Class

everyone. I am working on a site with smarty templates using php and a mysql database.
This is a more specific question than my first one which asked how to pass methods to a class. I thought it would be easier to repackage the question than edit the old one.
I have written a paginator script for my image gallery which displays images on the page. If a user has selected a category then only images in a particular category are shown and the results are always paginated.
The script is shown below.
$page_num = (isset($_GET['page_num']))?$_GET['page_num']:1; //if $_GET['page_num'] is set then assign to var $page_num. Otherwise set $page_num = 1 for first page
$category = (isset($_GET['req1']))?$_GET['req1']:'null'; //if $_GET['req1'] is set assign to $category other set $category to null
$items_pp = 5;
$total = $db->num_images_gallery($category); //returns the number of records in total('null') or in a particular category('category_name')
$pages_required = ceil($total/$items_pp); //total records / records to display per page rounded up
if($page_num > $pages_required){//in case the current page number is greater that the pages required then set it to the amount of pages required
$page_num = $pages_required;
}
if($page_num < 1){//in case the current page num is set to less that one set it back to 1
$page_num = 1;
}
$limit = "LIMIT " .($page_num - 1)*$items_pp . "," . $items_pp . ""; //if 5 results pre page and we on page 3 then LIMIT 10,5 that is record 10,11,12,13 and 14
$result = $db->get_images_gallery($category,$limit);
$i = 0;
while($row = $result->fetch_assoc()){
$images[$i]['file'] =$row['file'];
$images[$i]['file_thumb'] = str_replace('.','_thumbnail.',$row['file']);//show the thumbnail version of the image on the page
$images[$i]['title'] = $row['title'];
$images[$i]['description'] = $row['description'];
$i++;
}
if(!empty($images)){
$smarty->assign('images',$images);}else{
$smarty->assign('message',"There are no images to display in the ".ucwords(str_replace('_',' ',$category))." category");}
if($total > 0 && $pages_required >= 1){//only display this navigation if there are images to display and more than one page
$smarty->assign('page_scroll',$page_num . ' of ' . $pages_required);
$page_scroll_first = "<a href='".$_SERVER['REDIRECT_URL'] . "?page_num=1"."' >FIRST</a> <a href='".$_SERVER['REDIRECT_URL'] . "?page_num=" . ($page_num-1)."' ><<PREVIOUS</a>";
$page_scroll_last = " <a href='".$_SERVER['REDIRECT_URL'] . "?page_num=". ($page_num+1) . "'>NEXT>></a> <a href='" . $_SERVER['REDIRECT_URL'] . "?page_num=".$pages_required."'>LAST</a>";
if($page_num == 1){$page_scroll_first = "FIRST <<PREVIOUS";}
if($page_num == $pages_required){$page_scroll_last = "NEXT>> LAST";}
$smarty->assign('page_scroll_first',$page_scroll_first);//just use if statements to set the values for page scroll first and page scroll last and then assign them here
$smarty->assign('page_scroll_last',$page_scroll_last);
$smarty->assign('page_num',$page_num);
}
The script calls on two methods from my database class:
$db->num_images_gallery which looks like this:
function num_images_gallery($cat='null'){
$query = ($cat == 'null')?
"SELECT COUNT(*) AS images FROM images
LEFT JOIN image_categories ON (images.image_categories_id = image_categories.id)
WHERE images.gallery='1' AND image_categories.gallery = '1'"//no images should be shown in a category which is not intended to be shown at all
:
"SELECT COUNT(*) AS images FROM images
LEFT JOIN image_categories ON (images.image_categories_id = image_categories.id)
WHERE category = '{$cat}'
AND images.gallery='1' AND image_categories.gallery = '1'";
$result = $this->connection->query('SELECT COUNT(*) AS images FROM (?)',$x);
$row = $result->fetch_assoc();
$row_count = $row['images'];
echo $row_count;
return $row_count;
}
and the method $db::get_images_gallery() which looks like this:
function get_images_gallery($category,$limit){
$query = ($category=='null')?
"SELECT `file`,title,images.description,sizes,images.gallery,category FROM images
LEFT JOIN image_categories ON (images.image_categories_id = image_categories.id) WHERE images.gallery='1' AND image_categories.gallery = '1' {$limit}"
:
"SELECT `file`,title,images.description,sizes,images.gallery,category FROM images
LEFT JOIN image_categories ON (images.image_categories_id = image_categories.id)
WHERE category = '{$category}' AND images.gallery='1' AND image_categories.gallery = '1' {$limit}";
$result = $this->connection->query($query);
return $result;
}
I now want to create a class called paginate and put this script in it so i can display my site products paginated.
The main problem is that i need to use different functions to get the num of prodducts in my product table and then return the paginated results. How do i turn the script above into a class where i can change the functions which are used. I almost got an answer on my previous question, but the question was not specific enough.
Thanks
andrew
There's a Smarty Add-On for pagination.
You can find it here: http://www.phpinsider.com/php/code/SmartyPaginate/
For a quick example, extracted from the linked page:
index.php
session_start();
require('Smarty.class.php');
require('SmartyPaginate.class.php');
$smarty =& new Smarty;
// required connect
SmartyPaginate::connect();
// set items per page
SmartyPaginate::setLimit(25);
// assign your db results to the template
$smarty->assign('results', get_db_results());
// assign {$paginate} var
SmartyPaginate::assign($smarty);
// display results
$smarty->display('index.tpl');
function get_db_results() {
// normally you would have an SQL query here,
// for this example we fabricate a 100 item array
// (emulating a table with 100 records)
// and slice out our pagination range
// (emulating a LIMIT X,Y MySQL clause)
$_data = range(1,100);
SmartyPaginate::setTotal(count($_data));
return array_slice($_data, SmartyPaginate::getCurrentIndex(),
SmartyPaginate::getLimit());
}
index.tpl
{* display pagination header *}
Items {$paginate.first}-{$paginate.last} out of {$paginate.total} displayed.
{* display results *}
{section name=res loop=$results}
{$results[res]}
{/section}
{* display pagination info *}
{paginate_prev} {paginate_middle} {paginate_next}
Regarding your question about mixing the DB class and the Paginator class, it's all ok:
Your DB class will handle fetching data from DB
The SmartyPaginate class will handle the pagination
And your index.php just make the calls to each one where appropriate to set things out.
The idea is to keep responsibilities isolated.
Your DB class won't handle pagination, nor will your pagination class contain DB code.
From your other question, I think you were trying to do something too much convoluted for the problem at hand.
I'd suggest you to move all code that is DB-related inside your DB handling class and outside your index.php
This, for example:
$limit = "LIMIT " .($page_num - 1)*$items_pp . "," . $items_pp . ""; //if 5 results pre page and we on page 3 then LIMIT 10,5 that is record 10,11,12,13 and 14
This is DB logic, it generates (part of) an SQL string, so move it around.
It depends on 2 parameters, so find a way to get them available.
In this case, I'd suggest just passing both as parameters.
Instead of:
$result = $db->get_images_gallery($category,$limit);
Use:
$result = $db->get_images_gallery($category,$no_items, $page);
Also, your pager navigation rule should be inside your paginator class..
if($total > 0 && $pages_required >= 1){//only display this navigation if there are images to display and more than one page
$smarty->assign('page_scroll',$page_num . ' of ' . $pages_required);
$page_scroll_first = "<a href='".$_SERVER['REDIRECT_URL'] . "?page_num=1"."' >FIRST</a> <a href='".$_SERVER['REDIRECT_URL'] . "?page_num=" . ($page_num-1)."' ><<PREVIOUS</a>";
$page_scroll_last = " <a href='".$_SERVER['REDIRECT_URL'] . "?page_num=". ($page_num+1) . "'>NEXT>></a> <a href='" . $_SERVER['REDIRECT_URL'] . "?page_num=".$pages_required."'>LAST</a>";
if($page_num == 1){$page_scroll_first = "FIRST <<PREVIOUS";}
if($page_num == $pages_required){$page_scroll_last = "NEXT>> LAST";}
$smarty->assign('page_scroll_first',$page_scroll_first);//just use if statements to set the values for page scroll first and page scroll last and then assign them here
$smarty->assign('page_scroll_last',$page_scroll_last);
$smarty->assign('page_num',$page_num);
}
In this case, I hope the Add-On will handle it automatically for you.
You could then move this whole block, which does all your logic for fetching and preparing images data to a function (inside your ImageGalery class if you have one)
$total = $db->num_images_gallery($category); //returns the number of records in total('null') or in a particular category('category_name')
$pages_required = ceil($total/$items_pp); //total records / records to display per page rounded up
if($page_num > $pages_required){//in case the current page number is greater that the pages required then set it to the amount of pages required
$page_num = $pages_required;
}
if($page_num < 1){//in case the current page num is set to less that one set it back to 1
$page_num = 1;
}
$limit = "LIMIT " .($page_num - 1)*$items_pp . "," . $items_pp . ""; //if 5 results pre page and we on page 3 then LIMIT 10,5 that is record 10,11,12,13 and 14
$result = $db->get_images_gallery($category,$limit);
$i = 0;
while($row = $result->fetch_assoc()){
$images[$i]['file'] =$row['file'];
$images[$i]['file_thumb'] = str_replace('.','_thumbnail.',$row['file']);//show the thumbnail version of the image on the page
$images[$i]['title'] = $row['title'];
$images[$i]['description'] = $row['description'];
$i++;
}
Finally, on your index.php, all you have to do is:
Validate the parameters you received
Call your ImageGalery class to fetch the galery data (pass the parameters it needs)
Call your Pagination class to do the pagination (setting up navigation links, etc)
Set the Smarty template variables you need
And display it.
There is still lots of room for improvement, but I hope those few steps will help get your Image Galery code more clear.

Categories