Pagination Error - php

Im trying to do pages for my search result.My Search function is working fine. However, when I click on the page number. This error appears (below) :
Notice: Undefined index: search in C:\wamp\www\I-Document\new.php on line 8
ERROR: Select from dropdown
This message only should appear when there is no input in dropdown and no search input.
Im not sure how to correct this. Please help! Thank u
<?php
//connecting to the database
include 'config.php';
$search = mysql_escape_string($_POST['search']);
$dropdown = mysql_escape_string($_POST['dropdown']);
if (empty($search) && empty($dropdown)) {
die("Please choose your Search Criteria");
}
//max displayed per page
$per_page = 10;
//get start variable
$start = $_GET['start'];
//count records
$record_count = mysql_query("SELECT COUNT(*) FROM document WHERE $dropdown LIKE '%$search%'");
//count max pages
$max_pages = $record_count / $per_page;
if (!$start)
$start = 0;
//display data
$query = mysql_query("SELECT *
FROM document
WHERE $dropdown LIKE '%$search%'
LIMIT $start, $per_page");
echo "<b><center>Search Result</center></b><br>";
$num=mysql_num_rows($query);
if ($num==0)
echo "No results found";
else {
echo "$num results found!<p>";
}
echo "You searched for <b>$search</b><br /><br /><hr size='1'>";
echo "<table border='1' width='600'>
<th>File Reference No.</th>
<th>File Name</th>
<th>Owner</th>
<th>Borrow</th>
</tr>";
while ($rows = mysql_fetch_assoc($query)) {
echo "<tr>";
echo "<td>". $rows['file_ref'] ."</td>";
echo "<td>". $rows['file_name'] ."</td>";
echo "<td>". $rows['owner'] ."</td>";
echo "<td>Borrow</td>";
echo "</tr>";
}
echo "</table>";
//setup prev and next variables
$prev = $start - $per_page;
$next = $start + $per_page;
//show prev button
if (!($start<=0))
echo "<a href='new.php?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='new.php?start=$x'>$i</a> ";
else
echo " <a href='new.php?start=$x'><b>$i</b></a> ";
$i++;
}
}
//show next button
if (!($start>=$record_count-$per_page))
echo " <a href='new.php?start=$next'>Next</a>";
?>

Looks to me like when you click on a link, you no longer have the POST data being sent (it becomes a simple GET request). You'll need to create a form, then have a submit button for each of the pages. Or have the search term in the Query String, like Google (google.com/search?q=your+search+term+here)

This is the offending line
$search = mysql_escape_string($_POST['search']);
Your logic goes
IF $_POST['submit'] IS NOT SET
THEN
$search = mysql_escape_string($_POST['search']);
It's a pretty safe bet to say that if $_POST['submit'] is not set, then neither is $_POST['search']
Also, consider when you click one of your "page" links, that will issue a GET request and $_POST will be empty. You can either pass your POST parameters via GET along with the pagination data and look for them in either $_GET or $_POST (or $_REQUEST if you're feeling saucy), or create your pagination control as a "postable" form.

You already have all the code. You just need to rewrite your error condition.
Get the input variables
Encode them
Test for presence of both or die() with error message
So from your description:
$search = mysql_escape_string($_POST['search']);
$dropdown = mysql_escape_string($_POST['dropdown']);
if (empty($search) && empty($dropdown)) {
die("ERROR: whatever");
}
In this case you can test with empty() even after the escaping, because it would be an empty string in any case.

if (isset($_POST["search"])){
$search = mysql_escape_string($_POST['search']);
}else{
$search = mysql_escape_string($_GET['search']);
}
do the same for $_POST['dropdown']
but when printing out each page link , you should add the &search= and &dropdown= in the href of the page number .

Related

PHP If the number of an element was more than an amount, separate elements into two or more pages [duplicate]

I have some code that LIMITs data to display only 4 items per page. The column I'm using has about 20-30 items, so I need to make those spread out across the pages.
On the first page, I have:
$result = mysqli_query($con,"SELECT * FROM menuitem LIMIT 4");
{
echo "<tr>";
echo "<td align='center'><img src=\"" . $row['picturepath'] . "\" /></td>";
echo "<td align='center'>" . $row['name'] . "</td> <td align='center'> <input type='button' value='More Info'; onclick=\"window.location='more_info.php?';\"> </td>";
echo "<td align='center'>" . $row['price'] . "</td> <td align='center'> <input type='button' value='Add to Order' onclick=''> </td>";
echo "</tr>";
}
echo "</table>";
mysqli_close($con);
?>
<table width="1024" align="center" >
<tr height="50"></tr>
<tr>
<td width="80%" align="right">
NEXT
</td>
<td width="20%" align="right">
MAIN MENU
</td>
</tr>
</table>
You'll notice towards the bottom of the page my anchor tag within lists the second page, "itempage2.php". In item page 2, I have the same code, except my select statement lists the offset of 4.
$result = mysqli_query($con,"SELECT * FROM menuitem LIMIT 4 offset 4");
This works, this way when there is a pre-determined number of items within my database. But it's not that good. I need to create a new page only if there are more items, not hard-coded into it like it is now.
How can I create multiple pages without having to hard-code each new page, and offset?
First off, don't have a separate server script for each page, that is just madness. Most applications implement pagination via use of a pagination parameter in the URL. Something like:
http://yoursite.com/itempage.php?page=2
You can access the requested page number via $_GET['page'].
This makes your SQL formulation really easy:
// determine page number from $_GET
$page = 1;
if(!empty($_GET['page'])) {
$page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT);
if(false === $page) {
$page = 1;
}
}
// set the number of items to display per page
$items_per_page = 4;
// build query
$offset = ($page - 1) * $items_per_page;
$sql = "SELECT * FROM menuitem LIMIT " . $offset . "," . $items_per_page;
So for example if input here was page=2, with 4 rows per page, your query would be:
SELECT * FROM menuitem LIMIT 4,4
So that is the basic problem of pagination. Now, you have the added requirement that you want to understand the total number of pages (so that you can determine if "NEXT PAGE" should be shown or if you wanted to allow direct access to page X via a link).
In order to do this, you must understand the number of rows in the table.
You can simply do this with a DB call before trying to return your actual limited record set (I say BEFORE since you obviously want to validate that the requested page exists).
This is actually quite simple:
$sql = "SELECT your_primary_key_field FROM menuitem";
$result = mysqli_query($con, $sql);
$row_count = mysqli_num_rows($result);
// free the result set as you don't need it anymore
mysqli_free_result($result);
$page_count = 0;
if (0 === $row_count) {
// maybe show some error since there is nothing in your table
} else {
// determine page_count
$page_count = (int)ceil($row_count / $items_per_page);
// double check that request page is in range
if($page > $page_count) {
// error to user, maybe set page to 1
$page = 1;
}
}
// make your LIMIT query here as shown above
// later when outputting page, you can simply work with $page and $page_count to output links
// for example
for ($i = 1; $i <= $page_count; $i++) {
if ($i === $page) { // this is current page
echo 'Page ' . $i . '<br>';
} else { // show link to other page
echo 'Page ' . $i . '<br>';
}
}
A dozen pages is not a big deal when using OFFSET. But when you have hundreds of pages, you will find that OFFSET is bad for performance. This is because all the skipped rows need to be read each time.
It is better to remember where you left off.
If you want to keep it simple go ahead and try this out.
$page_number = mysqli_escape_string($con, $_GET['page']);
$count_per_page = 20;
$next_offset = $page_number * $count_per_page;
$cat =mysqli_query($con, "SELECT * FROM categories LIMIT $count_per_page OFFSET $next_offset");
while ($row = mysqli_fetch_array($cat))
$count = $row[0];
The rest is up to you.
If you have result comming from two tables i suggest you try a different approach.
Use .. LIMIT :pageSize OFFSET :pageStart
Where :pageStart is bound to the_page_index (i.e. 0 for the first page) * number_of_items_per_pages (e.g. 4) and :pageSize is bound to number_of_items_per_pages.
To detect for "has more pages", either use SQL_CALC_FOUND_ROWS or use .. LIMIT :pageSize OFFSET :pageStart + 1 and detect a missing last (pageSize+1) record. Needless to say, for pages with an index > 0, there exists a previous page.
If the page index value is embedded in the URL (e.g. in "prev page" and "next page" links) then it can be obtained via the appropriate $_GET item.

How do i get specific records with sql? [duplicate]

I have some code that LIMITs data to display only 4 items per page. The column I'm using has about 20-30 items, so I need to make those spread out across the pages.
On the first page, I have:
$result = mysqli_query($con,"SELECT * FROM menuitem LIMIT 4");
{
echo "<tr>";
echo "<td align='center'><img src=\"" . $row['picturepath'] . "\" /></td>";
echo "<td align='center'>" . $row['name'] . "</td> <td align='center'> <input type='button' value='More Info'; onclick=\"window.location='more_info.php?';\"> </td>";
echo "<td align='center'>" . $row['price'] . "</td> <td align='center'> <input type='button' value='Add to Order' onclick=''> </td>";
echo "</tr>";
}
echo "</table>";
mysqli_close($con);
?>
<table width="1024" align="center" >
<tr height="50"></tr>
<tr>
<td width="80%" align="right">
NEXT
</td>
<td width="20%" align="right">
MAIN MENU
</td>
</tr>
</table>
You'll notice towards the bottom of the page my anchor tag within lists the second page, "itempage2.php". In item page 2, I have the same code, except my select statement lists the offset of 4.
$result = mysqli_query($con,"SELECT * FROM menuitem LIMIT 4 offset 4");
This works, this way when there is a pre-determined number of items within my database. But it's not that good. I need to create a new page only if there are more items, not hard-coded into it like it is now.
How can I create multiple pages without having to hard-code each new page, and offset?
First off, don't have a separate server script for each page, that is just madness. Most applications implement pagination via use of a pagination parameter in the URL. Something like:
http://yoursite.com/itempage.php?page=2
You can access the requested page number via $_GET['page'].
This makes your SQL formulation really easy:
// determine page number from $_GET
$page = 1;
if(!empty($_GET['page'])) {
$page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT);
if(false === $page) {
$page = 1;
}
}
// set the number of items to display per page
$items_per_page = 4;
// build query
$offset = ($page - 1) * $items_per_page;
$sql = "SELECT * FROM menuitem LIMIT " . $offset . "," . $items_per_page;
So for example if input here was page=2, with 4 rows per page, your query would be:
SELECT * FROM menuitem LIMIT 4,4
So that is the basic problem of pagination. Now, you have the added requirement that you want to understand the total number of pages (so that you can determine if "NEXT PAGE" should be shown or if you wanted to allow direct access to page X via a link).
In order to do this, you must understand the number of rows in the table.
You can simply do this with a DB call before trying to return your actual limited record set (I say BEFORE since you obviously want to validate that the requested page exists).
This is actually quite simple:
$sql = "SELECT your_primary_key_field FROM menuitem";
$result = mysqli_query($con, $sql);
$row_count = mysqli_num_rows($result);
// free the result set as you don't need it anymore
mysqli_free_result($result);
$page_count = 0;
if (0 === $row_count) {
// maybe show some error since there is nothing in your table
} else {
// determine page_count
$page_count = (int)ceil($row_count / $items_per_page);
// double check that request page is in range
if($page > $page_count) {
// error to user, maybe set page to 1
$page = 1;
}
}
// make your LIMIT query here as shown above
// later when outputting page, you can simply work with $page and $page_count to output links
// for example
for ($i = 1; $i <= $page_count; $i++) {
if ($i === $page) { // this is current page
echo 'Page ' . $i . '<br>';
} else { // show link to other page
echo 'Page ' . $i . '<br>';
}
}
A dozen pages is not a big deal when using OFFSET. But when you have hundreds of pages, you will find that OFFSET is bad for performance. This is because all the skipped rows need to be read each time.
It is better to remember where you left off.
If you want to keep it simple go ahead and try this out.
$page_number = mysqli_escape_string($con, $_GET['page']);
$count_per_page = 20;
$next_offset = $page_number * $count_per_page;
$cat =mysqli_query($con, "SELECT * FROM categories LIMIT $count_per_page OFFSET $next_offset");
while ($row = mysqli_fetch_array($cat))
$count = $row[0];
The rest is up to you.
If you have result comming from two tables i suggest you try a different approach.
Use .. LIMIT :pageSize OFFSET :pageStart
Where :pageStart is bound to the_page_index (i.e. 0 for the first page) * number_of_items_per_pages (e.g. 4) and :pageSize is bound to number_of_items_per_pages.
To detect for "has more pages", either use SQL_CALC_FOUND_ROWS or use .. LIMIT :pageSize OFFSET :pageStart + 1 and detect a missing last (pageSize+1) record. Needless to say, for pages with an index > 0, there exists a previous page.
If the page index value is embedded in the URL (e.g. in "prev page" and "next page" links) then it can be obtained via the appropriate $_GET item.

Pagination script doesn't work with datatables

I've been dealing with tihs problem for more than two days but still couldn't find what's the problem. I am trying to build a pagination system for my search results. Code works perfectly fine when I run it in new php file but when it comes to display those result in a table I constantly keep getting that Error! message inside of the last else section. Plus, wherever I place for loop for page numbers it always showing before the table. Think I was so busy with dealing with this problem I am focusing to the same point. Help, please!
edit I've just deleted all conditional statements and got undefined index for all my variables that I get by POST method. That's the problem but still don't know what might be the solution for this.
<?php
if (isset($_POST['search_btn'])) {
include_once "db_connect.php";
$from = $_POST['from'];
$where = $_POST['where'];
$date = $_POST['date'];
$type = $_POST['type'];
$proc_id = $_POST['proc_id'];
if(empty($from) || empty($where) || empty($date) || empty($type)){
header("Location: index.php?search=empty");
exit();
}else{
//define how many results you want per page
$results_per_page = 10;
//number of results stored in database
"SELECT * FROM proc WHERE p_from = '".$from."' and p_where = '".$where."' and type= '".$type."' ";
$result = mysqli_query($conn, $sql);
$number_of_results = mysqli_num_rows($result);
//determine number of total pages available
$number_of_pages = ceil($number_of_results/$results_per_page);
//determine which page number visitor is currently on
if (!isset($_GET['page'])) {
$page = 1;
} else {
$page = $_GET['page'];
}
//determine the SQL LIMIT starting number for the result on the displaying page
$this_page_first_result = ($page-1)*$results_per_page;
//retrive selected results from database and display them on page $sql='SELECT * FROM proc LIMIT ' . $this_page_first_result . ',' . $results_per_page;
$result = mysqli_query($conn, $sql);
while($rows = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
echo '<tr onclick="content(\''. $rows['proc_id'] .'\')">';
echo "<td>" .$rows['p_name'] . " " . $rows['p_surname']. " </td>";
echo "<td>" .$rows['p_from']. "</td>";
echo "<td>" .$rows['p_where']. "</td>";
echo "<td>" .$rows['p_date']. "</td>";
echo "<td>" .$rows['price']. "</td>";
echo "<td>" .$rows['type']. "</td>";
echo "</tr>";
}
}
//display the links to the pages
for ($page=1;$page<=$number_of_pages;$page++) {
echo '' . $page . ' ';
}
}else{
echo "Error!";
}
?>
I'm just going to assume that the initial display works, but that pagination is giving you problems?
You're using POST values to pass the data from the search form to your code, however, when you then click the pagination links you are transferred to the search page, and lose those values.
You could change the next page URL to be a form and you pass each necessary value as a hidden input field. However, this has the drawback that when you hit the back button in your browser that it'll complain and ask you to resubmit the form data.
Another solution would be to store these post params in a session, cookie, whatever really. But in my opinion, that's not too great of a solution for this issue either.
I'd suggest you use GET parameters and then pass those in the next page button as well. This has the added benefit of being able to bookmark your searches.
Good luck!
As a side note, instead of building your query using concatenation you should use prepared statements. See the docs for the functions I used in the converted code below: https://www.php.net/manual/en/class.mysqli-stmt.php
if ($statement = mysqli_prepare($conn, "SELECT * FROM proc WHERE p_from = ? AND p_where = ? AND type = ?")) {
mysqli_stmt_bind_param($statement, "s", $from);
mysqli_stmt_bind_param($statement, "s", $where);
mysqli_stmt_bind_param($statement, "s", $type);
$result = mysqli_stmt_get_result($statement);
}

How to pass details from a SQL query to a details.php page

Very new to PHP so please go easy on me :)
I need to show the product details (manufacturer, tag number, etc) of a product if it's clicked by the user after being shown the results page. User types in a search form initially, then I get the catalogue_query.php to show the results, images, etc, that's all good. Each product has its own unique id which I thankfully get it to show in the url of the details.php page so I am doing something right.
However when I click on an item, even though I do get the "details.php" page shown with the correct id in the URL all it returns is the image and details for the very first item in the DB, not the actual item I clicked on - in other words the image and details do not match the id in the url.
Here is my code to show the results:
<?php
$query = $_POST ['query'];
$db = mysqli_connect ('localhost','root','root','asset_catalog');
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($db,"SELECT * FROM assets WHERE Description LIKE '%$query%' OR Manufacturer LIKE '%$query%' ORDER BY Description ");
echo "<table border='0'>
<tr>
</tr>";
while($row = mysqli_fetch_array($result))
{
if (($i % 5) == 0) echo "<tr>";
echo "<td><img src='".$row['Image']."' id='queryimg'><br>
<a href='details.php?ID=".$row['ID']."' style='color: #fff;'>{$row[Description]}</a></td>";
if (($i % 5) == 4) echo "</tr>";
$i++;
}
if ( $i > 0 && ($i-1) % 3 < 2) echo "</tr>";
echo "</table>";
?>
And here is my php for the details.php page:
<?php
$db = mysqli_connect ('localhost','root','root','asset_catalog');
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$ID = isset($_GET['ID']) ? (int) $_GET['ID'] : null;
$result = mysqli_query($db,"SELECT * FROM assets WHERE ID = $ID");
$row = mysqli_fetch_array($result);
echo "<table border='0'>
<tr>
</tr>";
echo "<tr>";
echo "<td><img src='".$row['Image']."' id='queryimg_details'>
<br>
{$row[Description]}</a>
<br>
{$row[Manufacturer]}
<br>
{$row[Tag_Num]}</td>";
echo "</tr>";
?>
Could anyone point me in the right direction? I am lost as to what I am doing wrong - or not doing.
Thanks a lot in advance!
$row can have multiple entries, so you should loop over it:
foreach($row as $r) {
// do stuff with this row like $r['Image']
}
You might want to change the variables names too.

Pagination using MySQL LIMIT, OFFSET

I have some code that LIMITs data to display only 4 items per page. The column I'm using has about 20-30 items, so I need to make those spread out across the pages.
On the first page, I have:
$result = mysqli_query($con,"SELECT * FROM menuitem LIMIT 4");
{
echo "<tr>";
echo "<td align='center'><img src=\"" . $row['picturepath'] . "\" /></td>";
echo "<td align='center'>" . $row['name'] . "</td> <td align='center'> <input type='button' value='More Info'; onclick=\"window.location='more_info.php?';\"> </td>";
echo "<td align='center'>" . $row['price'] . "</td> <td align='center'> <input type='button' value='Add to Order' onclick=''> </td>";
echo "</tr>";
}
echo "</table>";
mysqli_close($con);
?>
<table width="1024" align="center" >
<tr height="50"></tr>
<tr>
<td width="80%" align="right">
NEXT
</td>
<td width="20%" align="right">
MAIN MENU
</td>
</tr>
</table>
You'll notice towards the bottom of the page my anchor tag within lists the second page, "itempage2.php". In item page 2, I have the same code, except my select statement lists the offset of 4.
$result = mysqli_query($con,"SELECT * FROM menuitem LIMIT 4 offset 4");
This works, this way when there is a pre-determined number of items within my database. But it's not that good. I need to create a new page only if there are more items, not hard-coded into it like it is now.
How can I create multiple pages without having to hard-code each new page, and offset?
First off, don't have a separate server script for each page, that is just madness. Most applications implement pagination via use of a pagination parameter in the URL. Something like:
http://yoursite.com/itempage.php?page=2
You can access the requested page number via $_GET['page'].
This makes your SQL formulation really easy:
// determine page number from $_GET
$page = 1;
if(!empty($_GET['page'])) {
$page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT);
if(false === $page) {
$page = 1;
}
}
// set the number of items to display per page
$items_per_page = 4;
// build query
$offset = ($page - 1) * $items_per_page;
$sql = "SELECT * FROM menuitem LIMIT " . $offset . "," . $items_per_page;
So for example if input here was page=2, with 4 rows per page, your query would be:
SELECT * FROM menuitem LIMIT 4,4
So that is the basic problem of pagination. Now, you have the added requirement that you want to understand the total number of pages (so that you can determine if "NEXT PAGE" should be shown or if you wanted to allow direct access to page X via a link).
In order to do this, you must understand the number of rows in the table.
You can simply do this with a DB call before trying to return your actual limited record set (I say BEFORE since you obviously want to validate that the requested page exists).
This is actually quite simple:
$sql = "SELECT your_primary_key_field FROM menuitem";
$result = mysqli_query($con, $sql);
$row_count = mysqli_num_rows($result);
// free the result set as you don't need it anymore
mysqli_free_result($result);
$page_count = 0;
if (0 === $row_count) {
// maybe show some error since there is nothing in your table
} else {
// determine page_count
$page_count = (int)ceil($row_count / $items_per_page);
// double check that request page is in range
if($page > $page_count) {
// error to user, maybe set page to 1
$page = 1;
}
}
// make your LIMIT query here as shown above
// later when outputting page, you can simply work with $page and $page_count to output links
// for example
for ($i = 1; $i <= $page_count; $i++) {
if ($i === $page) { // this is current page
echo 'Page ' . $i . '<br>';
} else { // show link to other page
echo 'Page ' . $i . '<br>';
}
}
A dozen pages is not a big deal when using OFFSET. But when you have hundreds of pages, you will find that OFFSET is bad for performance. This is because all the skipped rows need to be read each time.
It is better to remember where you left off.
If you want to keep it simple go ahead and try this out.
$page_number = mysqli_escape_string($con, $_GET['page']);
$count_per_page = 20;
$next_offset = $page_number * $count_per_page;
$cat =mysqli_query($con, "SELECT * FROM categories LIMIT $count_per_page OFFSET $next_offset");
while ($row = mysqli_fetch_array($cat))
$count = $row[0];
The rest is up to you.
If you have result comming from two tables i suggest you try a different approach.
Use .. LIMIT :pageSize OFFSET :pageStart
Where :pageStart is bound to the_page_index (i.e. 0 for the first page) * number_of_items_per_pages (e.g. 4) and :pageSize is bound to number_of_items_per_pages.
To detect for "has more pages", either use SQL_CALC_FOUND_ROWS or use .. LIMIT :pageSize OFFSET :pageStart + 1 and detect a missing last (pageSize+1) record. Needless to say, for pages with an index > 0, there exists a previous page.
If the page index value is embedded in the URL (e.g. in "prev page" and "next page" links) then it can be obtained via the appropriate $_GET item.

Categories