How to create page numbers (for navigation) on a web page - php

I am writing PHP script to display data from the database (Mysql) on my webpage. I don't want all the information to display on a single page to avoid scrolling. However, I want to display only a few and then use page numbers to navigate to the rest. I managed to create the page numbers and yet still all the information is showing on a single page. Below is my code:
<?php
include('./includes/DB_Config.php');
$status = 1;
// Set number of Post per page for navigation
$post_per_page = 2;
if (isset($_GET['page']))
{
$startP = ($_GET['page'] - 1) * $post_per_page;
}
else
{
$startP = 0;
}
$post = mysqli_query ($mySQL_Conn, "SELECT * FROM BlogPost WHERE status = '$status'");
// Fetch Data or number of rows
$dataRw = mysqli_num_rows($post);
$pages = $dataRw / $post_per_page;
if ($dataRw == 0)
{
$_SESSION['NoPost'] = "No Post Found!";
}
else
{
unset($_SESSION['NoPost']);
//$pages = ceil($dataRw / $rows_per_page);
//$pages = array_slice($dataRw, $startP, $post_per_page);
while ($data = mysqli_fetch_array($post)) //Fetch data in array
{
//Assign data to variabes
$name = $data['blogger_Name'];
$postDate = $data['dateTime'];
$blogpost = $data['blog_message'];
$date = strtotime($postDate);
?>
<p> <span><?php echo $_SESSION['NoPost'] ; ?> </span></p>
<p> <span>By:</span><?php echo $name; ?> </p>
<p> <span>Posted On: </span> <?php echo date("j F Y", $date); ?> </p>
<p> <span>Post: </span><?php echo $blogpost; ?> </p>
<?php
}
}
?>
<hr>
<?php
for ($currentpage = 0; $currentpage < $pages; $currentpage++ )
{
?>
<span> <?php echo $currentpage + 1; ?> </span>
<?php
}
?>

What you are trying to accomplish is a very common pattern, and it's called pagination.
You can use LIMIT and OFFSET in your mysql queries to get only a certain subset of the data, and you can use this for basic pagination.
For example, if you want to display 50 results per page, and the user is on the third page, you set LIMIT to 50 and OFFSET to 2*50 (100), keep in mind the first page is an offset of 0 so we subtract the page by one.
You can use the following sql query to get a subset of data for a specific page.
"SELECT * FROM Users LIMIT $num_results OFFSET ".(($page_num-1)*$num_results);
You can get the total number of possible pages by getting the total row count from the Users table and dividing it by $num_results. A good idea might be to have your output script take a GET url query parameter that will be used as the page number.

Related

Using a generated list of options to refine PHP/MySQL search

I want to user a generated list of links to refine a search.
I have a database of products (panel meters), each row with a unique model number and information about that model. I've created a search that allows a user to search against model number and input type (these are process meters that can recieve signals like standard 4-20mA or custom ranges). Along with the search, the script also creates 3 unique arrays of links that I'd like to be clickable to narrow the results. It does that, so far, with these snippets of php to create the link list:
//create a series list
$uniqueseries[] = "<a href='#' onclick='document.searchform.submit()'>{$row['series']}</a>";
//create a inputs list
$uniqueinputs[] = "<a href='#' onclick='document.searchform.submit()'>{$row['sio']}</a>";
//create a series list
$uniquepowers[] = "<a href='#' onclick='document.searchform.submit()'>{$row['pso']}</a>";
AND
//create array of unique series types
$uniqueseries = array_unique($uniqueseries);
//create array of unique input types
$uniqueinputs = array_unique($uniqueinputs);
//create array of unique power types
$uniquepowers = array_unique($uniquepowers);
Which are located in the "backend" script (just a bit below.)
For each set of links, it first creates an array of non unique links (one for EVERY result MySQL originally returned) and then I use array_unique to cut down the array to only unique links. Then on my search page I use something like ", $uniqueseries); ?> to print out the array of links.
What I would like to happen is when a user clicks a link it narrows search results by resubmitting the original MySQL query with the refining query appended. An example of this behavior appears on Amazon search where a user can click a link on the left that will keep the same search but narrow it down to a certain department or even an option unique to that product (ie. amount of ram when searching for a computer or pixel count when searching for cameras.)
In my case, if my user starts the search by searching against model number and input type (the default two keys), say with the term "4 to 20", my user will have over 3500 results returned to them (we have a very large catalog of products.) On the left will be the list of unique links that I'd like to have refine the result. So if the user sees under "Power" options "120 V AC with battery backed data", I want clicking that link to return all meters with 4 to 20 mA inputs (there's multiple variations as you can see under the generated Input Options) but only if they have "120 V AC with battery backed data" as a "Power" source.
I feel like I'm on the right track but I'm still a bit of a novice when it comes to PHP.
To help along, here is the code I'm using for my search "backend":
<?php
//creates DB connection
$dbHost = 'host';
$dbUser = 'user';
$dbPass = 'pass';
$dbDatabase = 'db';
$con = mysql_connect($dbHost, $dbUser, $dbPass) or trigger_error("Failed to connect to MySQL Server. Error: " . mysql_error());
mysql_select_db($dbDatabase) or trigger_error("Failed to connect to database {$dbDatabase}. Error: " . mysql_error());
$time_start = microtime(true);
//create arrays for results and errors
$error = array();
$results = array();
//creates arrays holding values for narrowing results
$uniqueseries = array();
$uniqueinputs = array();
$uniquepowers = array();
$uniquedigsize = array();
$uniquedignum = array ();
$uniquedigcol = array();
$uniquedistype = array();
//reset some variables if needed
isset($_GET['page'])?"":$_GET['page'] = 1;
isset($resultcount)?"":$resultcount = 0;
if (isset($_GET['search'])) {
//removes HTML/JS
$searchString = trim($_GET['search']);
$searchStripped = strip_tags($searchString);
//prevents SQL injections
$searchSan = mysql_real_escape_string($searchStripped);
if (count($error) <1) { //search continues if no errors exist
$searchSQL = "SELECT series, model, img, pso, sio, dig_size, dig_num, dig_col FROM meters WHERE levenshtein('%{$searchSan}%',model) < 4 OR levenshtein('%{$searchSan}%',sio) < 4 ORDER BY model";
$searchResult = mysql_query($searchSQL) or trigger_error("There was an error with MySQL. " . mysql_error() . "<br> Query was {$searchSQL}.");
if (mysql_num_rows($searchResult) < 1) {
$error[] = "The search term '{$searchString}' yielded no results.";
} else {
$i = 1;
while ($row = mysql_fetch_assoc($searchResult)) {
$results[] = "<tr><td align='center'>{$i}</td> <td align='center'><a href='/catalog/{$row['series']}.pdf'>{$row['series']}</a></td> <td align='center'><img src='/img/productimg/small/{$row['img']}'></td> <td align='center'>{$row['model']}</td> <td> {$row['sio']}</td> <td> {$row['pso']}</td> <td align='center'>{$row['dig_num']}</td> <td align='center'>{$row['dig_size']}\"</td> <td align='center'>{$row['dig_col']}</td></tr>";
//create a series list
$uniqueseries[] = "<a href='#' onclick='document.searchform.submit()'>{$row['series']}</a>";
//create a inputs list
$uniqueinputs[] = "<a href='#' onclick='document.searchform.submit()'>{$row['sio']}</a>";
//create a series list
$uniquepowers[] = "<a href='#' onclick='document.searchform.submit()'>{$row['pso']}</a>";
$i++;
}
}
//create array of unique series types
$uniqueseries = array_unique($uniqueseries);
//create array of unique input types
$uniqueinputs = array_unique($uniqueinputs);
//create array of unique power types
$uniquepowers = array_unique($uniquepowers);
//results paginator
$resultcount = count($results); //number of results
$perpage = 5; //number of results per page
$totalpages = ceil($resultcount / $perpage); //calculates total number of pages
$startresult = (($_GET['page'] - 1) * $perpage); //calculates the first result number for page
$brokenresults = array_slice($results, $startresult, $perpage); //slices array into groups set by $perpage
$nextpage = $_GET['page'] + 1; //calculate next page number
$lastpage = $_GET['page'] - 1; //calculates last page number
}
}
function removeEmpty($var) {
return (!empty($var));
}
$execution_time = (microtime (true) - $time_start); //calculates script processing time
?>
And this is the code I'm using for my "frontend":
<body>
<!-- Google Analytics Script -->
<?php include_once("scripts/analyticstracking.php") ?>
<div class="wrapper"> <!-- Sticky Footer Wrapper -->
<div id="panorama"></div>
<div id="header">
<?php include("include/header/banner.php") ?>
<?php include("include/header/nav.php") ?>
<?php include("include/header/quicksearch.php") ?>
</div>
<form method="GET" action="<?php echo $_SERVER['PHP_SELF'];?>" name="searchform" id="searchform">
<div id="content">
<?php include("scripts/searchbackend.php") ?>
<?php include("scripts/searchform.php") ?>
<?php include("scripts/searchoptions.php") ?>
<div id="searchresults">
<center>
<?php
echo (count($error) > 0)?"The following had errors:<br /><span id=\"error\">" . implode("<br />", $error) . "</span><br /><br />":"";
echo ($resultcount > 0)?"<table id='searchtable' ><thead align='center'><tr><th width='50px'></th><th width='50px'>Series</th><th width='50px'>Image</th><th width='85px'>Model</th><th width='50px'>Input</th><th width='50px'>Power Supply</th><th width='50px'># of Digits</th><th width='50px'>Digit Size</th><th width='50px'>Display Color</th></tr></thead><tbody>" . implode("", $brokenresults) . "</tbody></table>":""; //returns results
?>
<div id="resultsfooter">
<?php
if (count($results) > 5) {
echo ($_GET['page'] > 1)?"<br><a href='/search.php?search={$_GET['search']}&page={$lastpage}'>Previous</a>" . " Page {$_GET['page']}/{$totalpages} " . "<a href='/search.php?search={$_GET['search']}&page={$nextpage}'>Next</a>":"<br>Page {$_GET['page']}/{$totalpages} " . "<a href='/search.php?search={$_GET['search']}&page={$nextpage}'>Next</a>";
}
echo ($resultcount > 0)?" | Search found {$resultcount} results in {$execution_time} seconds.":""; //result count and time
?>
</div>
</center>
</div>
</div>
</form>
</div>
<div class="footer">
<?php include("include/footer/footer.php") ?>
</div>
</body>
As well, this is the contents of my "searchoptions.php" include:
<div id="searchoptions">
<fieldset id="searchin" class="searchoptions">
<legend>Serach In</legend>
<input type="checkbox" class="checkbox" name="model" <?php echo isset($_GET['model'])?"checked":''; ?> /><label class='checklabel'>Model</label><br>
<input type="checkbox" class="checkbox" name="input" <?php echo isset($_GET['input'])?"checked":''; ?> /><label class='checklabel'>Input</label>
</fieldset>
<fieldset class="searchoptions" style="<?php if (count($uniqueseries) < 2) {echo "Display: none;";} ?>">
<legend>Series</legend>
<?php echo implode("<br>", $uniqueseries); ?>
</fieldset>
<fieldset class="searchoptions" style="<?php if (count($uniqueinputs) < 2) {echo "Display: none;";} ?>">
<legend>Input</legend>
<?php echo implode("<br>", $uniqueinputs); ?>
</fieldset>
<fieldset class="searchoptions" style="<?php if (count($uniquepowers) < 2) {echo "Display: none;";} ?>">
<legend>Power</legend>
<?php echo implode("<br>", $uniquepowers) ?>
</fieldset>
<input type="submit" class="" value="Update Search" style="" <?php if (!isset($types)) { if (isset($_GET['model'])) {"`model` LIKE '%{$searchSan}%'";} elseif (isset($_GET['input'])) {"`input` LIKE '%{$searchSan}%'";} } ?> />
</div>
I have my latest changes live on our test site which you can reach here:
new.foxmeter.com
Try searching "FM" or "4 to 20" as that's what I used in my examples. As of now, "4-20" and "4 20" don't return the same results as "4 to 20" but that I can do and it's not at the top of my list yet.
I'd also like previous searches to persist. So the search starts off "4 to 20", then narrows down to only 4 to 20 process meters with "120 V AC with battery backed data" power supply, then narrowing again will keep the "4 to 20 process with 120 V AC with battery backed data" refinement from before WITH new refinements as well.
If I've been unclear at any point, I'll be here all day so don't be afraid to question or correct me if you've got an idea for me. Thanks in advance to any help from anyone. I've gotten most of the features for our new site completed except for this search which I've had some trouble with so completing this means my task is (almost) complete.

Paginating MySql Results

I have a table that pulls tickets from a MYSQL database and displays them to the user. This part works wonderfully! But, once the user gets 5-10 tickets, the page becomes long and ugly. I am wanting to paginate the responses automatically to show maybe 5 tickets per page and show the rest on following pages.
I am using Bootstrap and have the following for the display of the pagination. "Although I fear this is only pseudo code" I added id's to each main element.
<ul class="pager" id="pagerUL">
<li class="previous" id="previousUL">
← Previous
</li>
<li class="next" id="nextUL">
Next →
</li>
</ul>
Essentially the only code used to pull the database information on the page is:
<?php if(count($tickets) > 0) : ?>
<?php foreach ($tickets as $ticket): ?>
//table content
<?php endforeach ?>
<?php else : ?>
<tr>
<td colspan="7">No Tickets Created.</td>
</tr>
<?php endif; ?>
I thought we could add something to the <?php if(count($tickets) > 0) : ?> But honestly, I am not sure as I am not a expert at php and never even attempted or had the need to build pagination up until now. Any help, guidance, thoughts would be appreciated.
Pass the page number thru the URL and then grab it via php with $_GET.
$page = $_GET['page'];
$per_page = 10; // Define it as you please
$start = $page*$per_page;
$query = "SELECT * FROM table LIMIT ".$start.", ".$per_page;
$result = mysql_query($query);
$count = mysql_num_rows($result);
$i = 0;
for($i=0;$i<$count;$i++)
{
//echo out what you want
echo "";
}
$total_pages = ceil($count/$per_page);
for($i=0;$i<$total_pages;$i++)
{
if($page != $i)
{
echo "<a href='/page.php?page=".$i."'>".$i."</a>";
} else
{
echo $i;
}
}

limited number of rows in a page

Hi I'm retrieving my data from DB
my data is (pic & name ) when I retrieved them I put them in 4 columns
now I wanna limit the number of rows in each page , I want each page shows three rows only
and if there is more data I want to make it display in next page
my code :
<?php
$items_in_row = 4 ;
$index = 0 ;
?>
<table>
<tr>
<?php
while ($row = mysql_fetch_array( $result , MYSQL_ASSOC)){
$index++ ; ?>
<td>
<p>
<img id='g1' src='/<?php echo $row["img"] ;?>' width=130 height=130 onClick='f1()'>
</p>
<p> Name: <?php echo $row['name'] ; ?> </p>
<br>
</td>
<?php if ($index%$items_in_row == 0){ ?>
</tr>
<tr>
<?php }
} ?>
</tr>
</table>
One way to do this is to use the LIMIT() function in SQL, passing in variables that you are storing in the session in PHP. Let's say you want 3 rows of 4 pictures on each page, then you want 12 pictures. So you do something like
select * from pictures LIMIT(0,12)
This returns the first 12 items.
You can do it by just tracking page number. Maybe you have a $page variable in your PHP. If you are on page 2, $page contains 2. Use that to construct a dynamic SQL query with your PHP maybe like this...
$sqlQueryStatement = "select * from pictures LIMIT(". ($page-1)*12 . ", 12)";
What this does is for page 2, it produces the sql statement:
select * from pictures LIMIT(12,12)
See how that works? Now you execute that SQL, and you have the set of results that should be output for page 2.
You can use some further logic to take these basic concepts and run with them...extending them to uses like creating the clickable pagination numbers on the bottom of your results and so forth.
i develop my pagination jobs using the following algorithm:
...1) selecting the results
$page = 1; // what page to show, if you dont know 1 is default.
$maxthingsperpage = 5; // how many things (etc. what you show) per page
$offset = ($page * $maxthingsperpage) - $maxthingsperpage; // db id to start reading
$result = mysql_query("SELECT * FROM things LIMIT ".$offset.",".$maxthingsperpage);
...2) display the things into page
$numrows = mysql_num_rows($result);
$numthingstodisplay = ($numrows > $maxthingsperpage ? $maxthingsperpage : $numrows);
while ($row = mysql_fetch_array( $result , MYSQL_ASSOC)) {
... display here without worrying about when to break; num rows are exact
}
you can replace $maxthingsperpage with your $items_in_row

How to allow multiple filters to be selected - pagination?

Hey, I am still trying to allow multiple filters to be selected for my pagination script but not sure how to do it being very new to php and programing in general.
So in my pagination, when a user clicks the 'marketing' button(link) it queries the database just for the category that = marketing. The same goes for the other 2 filter buttons as seen in the script below. (automotive, sports).
The problem is, I want to be able to select multiple filters like only marketing and auomotive or automotive and sports, for example if I click the marketing filter and then the automotive, it would display the categories that equal marketing, and automotive.
I have no idea how to accomplish this, so I have come to the experts to help me out.
This is the script I am working on:
<h3>Filter results by:</h3>
<a href='pagi_test.php?category=marketing'>marketing</a>
<a href='pagi_test.php?category=automotive'>automotive</a>
<a href='pagi_test.php?category=sports'>sports</a>
<br />
<h3>Results:</h3>
<?php
//connecting to the database
$error = "Could not connect to the database";
mysql_connect('localhost','root','root') or die($error);
mysql_select_db('ajax_demo') or die($error);
//max displayed per page
$per_page = 3;
//get start variable
$start = $_GET['start'];
$category = mysql_real_escape_string($_GET['category']);
//count records
$record_count = mysql_num_rows(mysql_query("SELECT * FROM explore WHERE category='$category'"));
//count max pages
$max_pages = $record_count / $per_page; //may come out as decimal
if (!$start)
$start = 0;
//display data
$get = mysql_query("SELECT * FROM explore WHERE category='$category' LIMIT $start, $per_page");
?>
<table width="800px">
<?php
while ($row = mysql_fetch_assoc($get))
{
// get data
$id = $row['id'];
$site_name = $row['site_name'];
$site_description = $row['site_description'];
?>
<tr>
<td><?php echo $id; ?></td>
<td><?php echo $site_name; ?></td>
<td><?php echo $site_description; ?></td>
</tr>
<?php
}
//setup prev and next variables
$prev = $start - $per_page;
$next = $start + $per_page;
//show prev button
if (!($start<=0))
echo "<a href='pagi_test.php?category=$category&start=$prev'>Prev</a> ";
//show page numbers
//set variable for first page
$i=1;
for ($x=0;$x<$record_count;$x=$x+$per_page)
{
if ($start!=$x)
echo " <a href='pagi_test.php?category=$category&start=$x'>$i</a> ";
else
echo " <a href='pagi_test.php?category=$category&start=$x'><b>$i</b></a> ";
$i++;
}
//show next button
if (!($start>=$record_count-$per_page))
echo " <a href='pagi_test.php?category=$category&start=$next'>Next</a>";
?>
Any help on this would be great. Thank you.
-- EDIT --
If anyone has a better method of doing a pagination system with multiple filters than the one above, please let me know.
While selecting second filter u can add the category
ex:
At first ur variable $category has
$category="Marketing";
When user filter with another category suppose automotive then add it to $category with a delimeter,Now
$category="Marketing:Automotive";
when u access thru GET use explode:
$cat=explode(":",$_GET['category']);
and write your condition
$condition="category=category[0]";
for($i=1; $i<sizeof($cat); $i++)
{
$condition="AND category=$cat[$i]";
}
$where="WHERE $condition";
use $where in ur query, like
$record_count = mysql_num_rows(mysql_query("SELECT * FROM explore $where"));
I see two separate issues
How to allow the user to select more than one category to filter by
How to propagate those choices to the pagination links
Each for which I have a solution!
How to allow the user to select more than one category to filter by
A form is going to be the most direct approach.
<h3>Filter results by:</h3>
<form action="pagi_test.php" method="GET">
<input type="checkbox" name="category[]" value="marketing" id="cat_marketing"/>
<label for="cat_marketing">Marketing</label>
<br/>
<input type="checkbox" name="category[]" value="automotive" id="cat_automotive"/>
<label for="cat_automotive">Automotive</label>
<br/>
<input type="checkbox" name="category[]" value="sports" id="cat_sports"/>
<label for="cat_sports">Marketing</label>
<br/>
<input type="submit" value="Filter!" />
</form>
Now, $_GET['category'] will be an array of every category that was selected.
$categories = $_GET['category'];
$inClause = "'" . implode( "','", array_map( 'mysql_real_escape_string', $categories ) ) . "'";
//count records
$record_count = mysql_num_rows(
mysql_query( "SELECT * FROM explore WHERE category IN($inClause)" )
);
Of course, you'd probably want to add a check here to make sure $categories isn't empty before you execute the query.
You'll need to modify the actual selection query as well
//display data
$get = mysql_query("SELECT * FROM explore WHERE category IN($inClause) LIMIT $start, $per_page");
Bingo! Now that part is done!
How to propagate those choices to the pagination links
Since we already have an array of the categories selected stored in $categories, this will be trivial using http_build_query().
//setup prev and next variables
$prev = $start - $per_page;
$next = $start + $per_page;
// Get the categories in an HTML-safe array
$requestVars = array_map( 'htmlspecialchars', $categories );
//show prev button
if (!($start<=0))
{
$requestVars['start'] = $prev;
echo 'Prev ';
}
//show page numbers
//set variable for first page
$i=1;
for ( $x = 0; $x < $record_count; $x = $x + $per_page )
{
$requestVars['start'] = $x;
if ( $start != $x )
{
echo ''. $i .' ';
} else {
echo '<b>'. $i .'</b> ';
}
$i++;
}
//show next button
if (!($start>=$record_count-$per_page))
{
$requestVars['start'] = $next;
echo 'Next ';
}
Now, there are still holes in this implementation.
Since the <form> is printed to the page before the rest of the logic, there's no way to pre-select the checkboxes that represent the current filter choices. Which you could definitely change.
Also, you have categories as literal strings in the PHP script - they would really be better in their own table in the database.
The way you retrieve a count for the entire data set is inefficient - it sends the entire data set over the wire to PHP, which then is responsible for determining the record count. It's much better to run a separate query that uses SELECT count(*) ... instead.

How to update sql query dynamically - jquery

I am trying to figure out how I can update my sql query dynamically.
On the main page, I have a pagination script that counts how many pages there will be:
<?php
function generate_pagination($sql) {
include_once('config.php');
$per_page = 3;
//Calculating no of pages
$result = mysql_query($sql);
$count = mysql_num_rows($result);
$pages = ceil($count/$per_page);
//Pagination Numbers
for($i=1; $i<=$pages; $i++)
{
echo '<li class="page_numbers" id="'.$i.'">'.$i.'</li>';
}
}
?>
I then have in the body of the same page this line of code to populate the page numbers:
<?php generate_pagination("SELECT * FROM explore WHERE category='marketing'"); ?>
So, that line is displaying the necessary amount of page numbers to be displayed for just the 'marketing' category.
The problem that I am having is with that single line of code. I want to make the category dynamic, so instead of it being hardcoded to 'marketing' I would like jquery to get the id of an element and place it in.
The element would be this link that I have on the same page:
Marketing
So, when the user clicks that link, I am trying to place the id of the link in the category section of the query using jquery.
I hope that made sense, and if anyone can assist me on this that would be great.
First, the PHP side:
<?php
function generate_pagination($sql) {
include_once('config.php');
$per_page = 3;
//Calculating no of pages
$result = mysql_query($sql);
$count = mysql_num_rows($result);
$pages = ceil($count/$per_page);
//Pagination Numbers
for($i=1; $i<=$pages; $i++)
{
echo '<li class="page_numbers" id="'.$i.'">'.$i.'</li>';
}
}
?>
<?php generate_pagination("SELECT * FROM explore WHERE category='" . mysql_real_escape_string ( $_POST ['category'] ) . "'"); ?>
Then in your jquery post:
$("a.category").click(function() {
$.post("test.php", { category: $(this).attr("id") },
function(data){
//Load your results into the page
});
});
On click we take the ID, pass it to the server as a post variable category, then on the server, grab it, escape it properly for security, and use that query. Load your results the same way you are now, that part doesn't change.

Categories