I have a simple pagination script for my search, but I'm facing some trouble.
When I change the page, the query returns to the initial definition.
Something like:
Definition: Select * from a;
Search: Select * from a where a.id = 1;
And then when I go to the 2nd page the query becames that: Select * from a; again.
The code: I have a form with some fields for the search and then the script:
$sqlCount_pre = "SELECT COUNT('*') FROM a ";
$sqlCount_pre .= " INNER JOIN b ON a.id = b.id ";
if( sizeof( $where ) ){
$sqlCount_pre .= ' WHERE '.implode( ' AND ',$where );
}
$max = 2;
$sqlCount = mysql_query($sqlCount_pre);
$sqlResult = ceil(mysql_result($sqlCount, 0) / $max);
$pg = (isset($_GET["pg"])) ? (int)$_GET["pg"] : 1 ;
$start = ($pg - 1) * $max;
$sqlQuery = "SELECT a.* FROM a ";
$sqlQuery .= " INNER JOIN b ON a.id = b.id ";
if( sizeof( $where ) ){
$sqlQuery .= ' WHERE '.implode( ' AND ',$where );
$sqlQuery .= " LIMIT $start, $max";
}else{
$sqlQuery .= " LIMIT $start, $max";
}
$sql = mysql_query($sqlQuery) or die(mysql_error());
Then i show the result in the page.
After that i put the page links, as in this code:
<?php
if($sqlResult > 1 && $pg<= $sqlResult){
for($i=1; $i<=$sqlResult; $i++){
echo "<a href='?pg=$i'>$i</a> ";
}
}
?>
Is there something wrong or missing in this code?
When you combine a search form with pagination, you need to embed the search parameters in the paging links.
<?php
if($sqlResult > 1 && $pg<= $sqlResult){
$query = $_GET;
for($i=1; $i<=$sqlResult; $i++){
$query['pg'] = $i;
echo "<a href='?" . http_build_query($query) ."'>$i</a> ";
}
}
?>
The above code takes everything in your current query string and adds in the applicable pg attribute when building the pagination links.
-- edit --
Combining a POST search form with pagination gets a little weird. There are a couple things you can do:
Use javascript to populate a hidden "page" field in the form when you click one of the pagination links, and resubmit the form, e.g.:
$('.pagination-link').on('click', function() {
$('#page').val($(this).html()); //where you have a hidden field #page
$('$searchform').submit();
});
OR
Change the form method to GET, and use the example I posted above
is_int() doc is here
$pg = (isset($_GET["pg"]) && is_int($_GET["pg"])) ? (int)$_GET["pg"] : 1 ;
of course with this there is no reason for (int)... because we've already established $_GET["pg"] as an int, so type conversion is moot.
$pg = (isset($_GET["pg"]) && is_int($_GET["pg"]) && $_GET["pg"] > 0) ? $_GET["pg"] : 1 ;
this will return 1 if
$_GET["pg"]
returns a string of numbers like "42". For an alternative and is_numeric and a description and comparison of the two check out this article.
If GET returns a string
pg_escape_string($_GET["pg"])
pg_escape_string doc
Back to your original question. When you change pages the limit is not being executed. So the offset and max are not being set. take a look at the query executed when you hit the second page. Are you calculating the offset correctly?
are you only specifying $pg in
echo "<a href='?pg=$i'>$i</a> ";
you'd have to put in the search term as well to pass it to the $where array. The count will be 0 if you don't and that's why the implode doesn't happen.
multiple variables here
Related
I have a simple form to search a table for the search term entered into that form.
$query = $_GET['term'];
$min_length = 1;
if(strlen($query) >= $min_length){
$query = htmlspecialchars($query);
$query = mysqli_real_escape_string($link, $query);
}
Here the variable 'query' is the search query posted from the form.
The query for the database looks like this
$sql = mysqli_query($link, "SELECT * FROM products WHERE `name` LIKE '%".$query."%' OR
`brand` LIKE '%".$query."%'
OR `description` LIKE '%".$query."%' OR `spec` LIKE '%".$query."%'
OR `category` LIKE '%".$query."%' OR `subcategory` LIKE '%".$query."%' AND status = 1
ORDER BY id DESC LIMIT $offset, $rowsperpage") OR die(mysqli_error($link));
So this works ok if I dont paginate results, but I need to paginate them.
I think I need to get this line of code to send the variable '$query' to each paginated page.
echo " <a href='{$_SERVER['PHP_SELF']}?$query¤tpage=$x'>$x</a> ";
'$x' is just the variable for the current page
My form is now set to method="get"
EDIT: Sorted (I think)
I had everything wrapped in a
if(isset( $_GET['submit'] ) ){
}
So it appears to me that when I went to any other page but the first page (the first time) that submit from my search form wasn't being posted again obviously, so there were no results to get.
When I took that 'if' out the pagination works. But is it ok not to have it?
You need to forward term parameter and current page index. Also you must add
offset $x*$pagesize
limit $pagesize
to your query...
A few thoughts here:
Before even getting into the pagination aspects, just by looking at your query, I would suggest you look at using a MySQL natural language full text search (http://dev.mysql.com/doc/refman/5.5/en/fulltext-natural-language.html). that would make your query something like this:
SELECT * FROM products
WHERE
MATCH (name, brand, description, spec, category, subcategory)
AGAINST :query
AND STATUS = 1
This requires a FULLTEXT index across the fields used in the search. This requires use of MyISAM engine for the table.
An interesting thing to note about using the full text search in the where clause like this is that it will return rows in order of "relevance". So, for example, a record that has a number of matches across DB columns for you search term will have higher relevance than a record with a single match. In most search uses cases like yours, this is desired behavior, and your current query does nothing at all to provide this sort of functionality.
Now on to pagination.
You would likely need to pass some additional parameters to indicate page. So say your parameters are like this:
// you should provide some validation for these parameters, but I am not showing that
$query = $_GET['term'];
$page = $_GET['page'];
You would also somewhere in your code have some value set to determine rows per page to be shown. This could even be in the form of a parameter as well if you want to let the user select number of rows per page.
$rows_per_page = $_GET['pagerows'];
// or simply something like $rows_per_page = 10;
Calculation of values to use in the LIMIT clause is trivial. I am assuming $page is 1-based (i.e. first page has value of 1)
$offset = ($page - 1) * $rows_per_page;
Putting it together with the query above you get:
SELECT * FROM products
WHERE
MATCH (name, brand, description, spec, category, subcategory)
AGAINST :query
AND STATUS = 1
LIMIT :offset, :pagerows
Note I am just using named parameter syntax in the queries. You should consider using prepared statements for these queries.
So that is is the simple use case. Now what if you want to show the user some indication as to the number of pages associated with the search result? This means that you need to understand how many rows the query would return if there was no LIMIT clause. There are a couple of ways of doing this. You could simply run the same query without the LIMIT first and get the number of rows from that query. This may be appropriate for cases where you were not accepting user input to filter the result set and the user could arrive in the pagination view on any arbitrary page number.
That does not seem to be the use cases realted to a search, so I will give you another option which may best suite the search query use case. That is the use of SQL_CALC_FOUND_ROWS keyword in conjunction with FOUND_ROWS() functions. Here is how it works.
You simply add SQL_CALC_FOUND_ROWS into you SELECT query like this:
SELECT SQL_CALC_FOUND_ROWS * FROM products
WHERE
MATCH (name, brand, description, spec, category, subcategory)
AGAINST :query
AND STATUS = 1
LIMIT :offset, :pagerows
Your query will return the paginated result as expected, but using the same DB connection, you can then make a follow-up query to get the number of "found rows" (i.e. rows in result set before applying LIMIT from the last query). That query is very simple:
SELECT FOUND_ROWS()
So here is how this may look from a coding perspective:
$sql = <<<EOT
SELECT SQL_CALC_FOUND_ROWS * FROM products
WHERE
MATCH (name, brand, description, spec, category, subcategory)
AGAINST :query
AND STATUS = 1
LIMIT :offset, :pagerows
EOT;
// perform query here
// work with your result set
while ($row = /* your row fetch logic here */) {
// do something with row
}
// now query DB again to get found rows
// you must use same DB connection used for initial query
// and you must not perform any queries between your initial
// SELECT and this query to get row count
$row_sql = 'SELECT FOUND_ROWS()';
// execute your query and read the value from the result
// lets assume you set this to a variable named $total_rows
// now simply determine number of available page by simple math and rounding
$page_count = ceil($total_rows / $rows_per_page);
Please try something like this:
pagination.php
<?php
function getPagingQuery($sql, $itemPerPage = 10)
{
if (isset($_GET['page']) && (int)$_GET['page'] > 0) {
$page = (int)$_GET['page'];
} else {
$page = 1;
}
// start fetching from this row number
$offset = ($page - 1) * $itemPerPage;
return $sql . " LIMIT $offset, $itemPerPage";
}
function getPagingLink($sql, $itemPerPage = 10,$strGet)
{
$result = mysql_query($sql) or die(mysql_error());
$pagingLink = '';
$totalResults = mysql_numrows($result);
$totalPages = ceil($totalResults / $itemPerPage);
// how many link pages to show
$numLinks = 10;
// create the paging links only if we have more than one page of results
if ($totalPages > 1) {
$self = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] ;
if (isset($_GET['page']) && (int)$_GET['page'] > 0) {
$pageNumber = (int)$_GET['page'];
} else {
$pageNumber = 1;
}
// print 'previous' link only if we're not
// on page one
if ($pageNumber > 1) {
$page = $pageNumber - 1;
if ($page > 1) {
$prev = " [Prev] ";
} else {
$prev = " [Prev] ";
}
$first = " [First] ";
} else {
$prev = ''; // we're on page one, don't show 'previous' link
$first = ''; // nor 'first page' link
}
// print 'next' link only if we're not
// on the last page
if ($pageNumber < $totalPages) {
$page = $pageNumber + 1;
$next = " [Next] ";
$last = " [Last] ";
} else {
$next = ''; // we're on the last page, don't show 'next' link
$last = ''; // nor 'last page' link
}
$start = $pageNumber - ($pageNumber % $numLinks) + 1;
$end = $start + $numLinks - 1;
$end = min($totalPages, $end);
$pagingLink = array();
for($page = $start; $page <= $end; $page++) {
if ($page == $pageNumber) {
$pagingLink[] = " $page "; // no need to create a link to current page
} else {
if ($page == 1) {
$pagingLink[] = " $page ";
} else {
$pagingLink[] = " $page ";
}
}
}
$pagingLink = implode(' | ', $pagingLink);
// return the page navigation link
$pagingLink = $first . $prev . $pagingLink . $next . $last;
}
return $pagingLink;
}
?>
product_search.php
$query = $_GET['term'];
$select = "SELECT * FROM products WHERE `name` LIKE '%".$query."%' ";
$strget="term=".$query;
$rowsPerPage =10;
$result= mysql_query(getPagingQuery($sel_products, $rowsPerPage, $strget)) or die(mysql_error());
$pagingLink = getPagingLink($sel_products, $rowsPerPage, $strget);
$num_rows = mysql_numrows($result);
if($num_rows > 0) {
while($array_in= mysql_fetch_array($result))
{
$product_id = $array_in['id'];
$product_name = $array_in['name'];
}
echo $pagingLink;
}
else
{
echo "No Results To Display";
}
I hope it should work.
How to add pagination in this code?
I want to limited data in one page and I want in bottom as:
1 2 3 4 5 6 8 9 10
If I click on page 2 then my more results show on that page.
How can I do like that ?
<?php
//connect to database
mysql_connect('localhost','root','pasword');
mysql_select_db('root');
/* Get the letter user clicked on and assign it a variable called $sort */
$sort = $_REQUEST['letter'];
/* Let's check if variable $sort is empty. If it is we will create a query to display all customers alphabetically ordered by last name. */
if($sort == ""){
$qry= "SELECT * FROM tree ORDER BY keywords ASC " ;
}else{
/* if varible $sort is not empty we will create a query that sorts out the customers by their last name, and order the selected records ascendingly. */
$qry = "SELECT * FROM tree WHERE keywords LIKE '$sort%' ORDER BY keywords ASC" ;
}
/* Notice the use of '%' wilde card in the above query "LIKE '$sort%'". */
//next step is to execute the query.
$execute = mysql_query($qry) or die(mysql_error());
/* Before we display results let's create our alphabetical navigation. The easiest way to create the navigation is to use character codes and run them through the "for" loop. */
echo "<p>" ;
for ($i = 65; $i < 91; $i++) {
printf('%s | ',
$PHP_SELF, chr($i), chr($i));
}
echo "</p>" ;
/* now we are ready to display the results. Since out tbl_customers table has only three fileds we will display the results in a paragraphs. In the real world you may need to display the results in a table.
To display the results we will use "do while" loop to fetch the results. If no customers are found we will display an error message. */
if(mysql_num_rows($execute)>0){
do{
echo "<p>" .$result['id']. " " .$result['keywords']. " " .$result['meaning']. "</p>" ;
}while($result = mysql_fetch_assoc($execute));
}else{
echo "<p>No customer found.</p>" ;
}
?>
First select no of datas to generate page numbers by total_number of rows by no of pages per page
mysql_num_rows($execute);
use limit command to limit the data like this
$qry= "SELECT * FROM tree ORDER BY keywords ASC limit 0,10 " ;
then for every page number increment the limit index
You can use the below code
$page = $_GET['page'];
if ($page < 1)
{
$page = 1;
}
$conc=mysql_connect('localhost','root','');
mysql_select_db('employer',$conc);
$resultsPerPage = 5;
$startResults = ($page - 1) * $resultsPerPage;
$query = mysql_query('SELECT * FROM employee ') or die(mysql_error());
$numberOfRows=mysql_num_rows($query);
$totalPages = ceil($numberOfRows / $resultsPerPage);
$query = mysql_query("SELECT * FROM employee LIMIT $startResults,$resultsPerPage");
while ($output = mysql_fetch_assoc($query))
{
$result[]=$output;
}
for($i = 1; $i <= $totalPages; $i++)
{
if($i == $page)
echo '<strong>'.$i.'</strong> ';
else
echo ''.$i.' ';
}
$page = intval(abs($_GET['page'])); // get security ONE
if(mysql_num_rows($sql)) // get page number to empty location index.php
{
header('Location: index.php');
}
I don't know how to make the search through another table. how should i do that?
the table name is comments and i want to search for all the post stored in the column name kom
Another thing is that i cant get the pagination start working...
I started the pagination within an else statment because i only need it when i get more than 1 result.
I can get the page links showing and limit the search posting showing but when i click on one off the links i cant get to the next page
Heres the code
<?php
$search = $_POST["search"];
$field = $_POST["field"];
if($_POST["submit"] && $search)
{
echo "<div id='result'>";
echo "<h2>Resultat</h2>";
$search = strtoupper($search);
$search = strip_tags($search);
$search = trim($search);
$query = "SELECT * FROM blogTable WHERE title LIKE '%$search%'
UNION
SELECT * FROM blogTable WHERE post LIKE '%$search%'";
$result = mysql_query($query, $conn) or die(mysql_error());
$matches = mysql_num_rows($result);
if($matches == 0)
//code if serch didnt result any results
else if($matches == 1)
//code if the matches only 1
else
{
$per_page = 4;
$pages = ceil($matches / $per_page);
$page = (isset($_GET['page'])) ? (int)$_GET['page']: 1;
$start = ($page - 1) * $per_page;
$query2 = "SELECT * FROM blogTable WHERE title LIKE '%$search%'
UNION
SELECT * FROM blogTable WHERE post LIKE '%$search%' LIMIT $start, $per_page";
$result2 = mysql_query($query2, $conn) or die(mysql_error());
echo "<font size='-1'>Sökningen $search gav $matches resultat</font><br/>";
while ($r2 = mysql_fetch_array($result2))
{
$id = $r["id"];
$title = $r["title"];
$post = $r["post"];
$time = $r["time"];
echo "<br/><strong><a href='comment.php?id=$id'>$title</a></strong><br/>";
echo "<font size='-1'>".substr($post, 0, 60)."</font><br/>";
echo "<font size='-1'>".substr($post, 60, 70)."</font><br/>";
echo "<font size='-3'>$time</font><br/>";
}
//theese are showin but cannot click of any of them
if($pages >= 1 && $page <= $pages)
{
for($nr = 1; $nr <= $pages; $nr++)
{
if($nr == $page)
echo "<a href='?page=".$nr."' style='font-size:20px;'>$nr</a>";
else
echo "<a href='?page=".$nr."' style='font-size:15px;'>$nr</a> ";
}
}
}
}
?>
Is there a specific reason you are using a UNION?
If not, you can change:
$query = "SELECT * FROM blogTable WHERE title LIKE '%$search%'
UNION
SELECT * FROM blogTable WHERE post LIKE '%$search%'";
to:
$query = "SELECT * FROM blogTable WHERE (title LIKE '%$search%') OR (post LIKE '%$search%')";
Anyway, I would never execute the same query twice, just get the first x results if no start parameter was given (for example a page number in the query string) and calculate the start point when a start parameter was given.
And if you want the total, use a COUNT(*) query or change your query:
$query = "SELECT SQL_CALC_FOUND_ROWS * FROM blogTable WHERE (title LIKE '%$search%') OR (post LIKE '%$search%')";
One thing that catches the eye is that the code you show is vulnerable to SQL injection.
Get rid of the strip_tags() (if it's for security, in which case it's useless) and do a mysql_real_escape_string() on every value you use in the search queries, or check whether the value is actually a number when using int columns.
Another thing is that the <font> tag is outmoded. The cool CSS way of styling text is having an external CSS stylesheet, and defining in it something like
span.small { font-size: 12px; color: green }
and then using it in the HTML like so:
<span class="small">Text goes here</span>
that said, this probably belongs on CodeReview.SE....
First, I always recommend to use GET method and not POST method for searches and filters, next, maybe this pagination php class can help you.
First, I coded this, which looks inside a table, gets the last 10 entries, and displays them. The output is as expected, a list of the 10 last entries in the database.
$query = "SELECT dfid FROM downloads_downloads ORDER BY did DESC limit 10";
$dlresult = mysql_query( $query );
$i=0;
$num = mysql_num_rows ($dlresult);
while ($i < $num) {
$dfid= mysql_result($dlresult,$i,"dfid");
echo "<b>filenumber:</b> $dfid <br>";
++$i;
}
But I don't just need the filenumber. I need the actual filename and url from another table. So I added a select statement inside the while statement, using the file number.
But for some reason, this code only displays one filename instead of 10. I know, from the above code, it's getting all 10 file numbers.
$query = "SELECT dfid FROM downloads_downloads ORDER BY did DESC limit 10";
$dlresult = mysql_query( $query );
$i=0;
$num = mysql_num_rows ($dlresult);
while ($i < $num) {
$dfid= mysql_result($dlresult,$i,"dfid");
$query2 = "SELECT file_name, file_name_furl FROM downloads_files WHERE file_id = '$dfid'";
$dlresult2 = mysql_query( $query2 );
$dlfile_name= mysql_result($dlresult2,$i,"file_name");
$dlfile_name_furl= mysql_result($dlresult2,$i,"file_name_furl");
echo "filenumber: $dfid <br>"; //Shows 10, as expected.
echo "filename: $dlfile_name - $dlfile_name_furl <br>"; //Shows only 1?
++$i;
}
I can manually execute the sql statement and retrieve the file_name and file_name_furl from the table. So the data is right. PHP isn't liking the select within the while statement?
Looks like you're only going to ever have 1 row, in your 2nd select statement, because you are just selecting one row, with your where statement.
So, you're only going to ever have row 0 in the 2nd statement, so its only finding row 0 on the first loop. try instead:
$dlfile_name= mysql_result($dlresult2,0,"file_name");
$dlfile_name_furl= mysql_result($dlresult2,0,"file_name_furl");
However, insrtead of making 11 separate queries, try using just one:
$link = new mysqli(1,2,3,4);
$query = "SELECT downloads_downloads.dfid, downloads_files.file_name, downloads_files.file_name_furl FROM downloads_downloads LEFT OUTER JOIN downloads_files ON downloads_files.file_id = downloads_downloads.dfid ORDER BY downloads_downloads.dfid DESC limit 10;
$result = $link->query($query) ;
if((isset($result->num_rows)) && ($result->num_rows != '')) {
while ($row = $result->fetch_assoc()) {
echo "filenumber: $row['dfid'] <br>";
echo "filename: $row['file_name'] - $row['file_name_furl'] <br>";
}
Read up on mysql joins http://www.keithjbrown.co.uk/vworks/mysql/mysql_p5.php
I'm not sure if this is syntax correct, but it gives you the right idea =)
I am using the Select query as
SELECT id, ordering FROM `jos_menu` WHERE ordering='".$rec['ordering'] -'1' ."' AND parent = '0'
Here I need all the records whose ordering is less than 1 of the selected record's order($rec['ordering'] = getting from other select query ) when I am trying to echo the query I am not getting complete statement but getting only this -1' AND parent = '0'
here is the whole snippet
$where = ' WHERE (id = ' . implode( ' OR id = ', $cid ) . ')';//Pranav Dave Coded
echo $selquery = "SELECT id, ordering FROM `jos_menu`".$where; //Pranav Dave Coded
$db->setQuery( $selquery );//Pranav Dave Coded
$record = $db->loadAssocList(); //Pranav Dave Coded
if ($model->orderItem($id, -1)) {
echo "<pre>";
print_r($model);
/*exit;*/
//echo $updorderup = mysql_escape_string($model->_db->_sql);//Pranav Dave Coded
foreach($record as $rec)//Pranav Dave Coded
{
echo $aboverow = "SELECT id, ordering FROM `jos_menu` WHERE ordering='".$rec['ordering'] -'1' ."' AND parent = '0'";
$db->setQuery( $aboverow );
$above = $db->loadAssoc();
echo "<pre>";
print_r($above);
}//end of foreach
}//end of if
Please suggest me where I am getting wrong.....
It looks like you may need to unwrap the -1 from the quotes:
WHERE ordering='".($rec['ordering'] - 1)."' AND parent = '0'";
Why do you trying to put everything inline?
Why not to make some preparations first?
Why not to compare resulting query with sample one?
Why don't you check every step if it return proper result?
$val = $rec['ordering'] - 1;
//let's see if $cal has proper value:
echo $val."<br>";
$sql = "SELECT id, ordering FROM `jos_menu` WHERE ordering = $val AND parent = 0";
//let's see if query looks good:
echo $sql;
//let's print sampe query to compare:
echo "<br>" ;
echo "SELECT id, ordering FROM `jos_menu` WHERE ordering = 1 AND parent = 0";
As Daniel said, you need to remove the quotes around the -1. Currently its trying to minus a string, which it wouldn't be happy with at all ;)