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.
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.
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
<?php
mysql_select_db($database_XXX, $XXX);
$result= mysql_query("SELECT COUNT(*) FROM news");
$total = mysql_result($result, 0, 0);
// create a random number
mt_srand((double)microtime()*1000000);
$number = mt_rand()%$total;
// get a random entry
$result= mysql_query("SELECT * FROM news LIMIT $number, 5");
$row = mysql_fetch_array($result);
?>
This is the PHP code I'm using and it pulls up random data from the table I want but I can't seem to figure out how to have it not show the current post it's on. Will I need to throw in an if statement in? If I do where would it go and how to impletment it. The only thing I can thing of is using if statements to check if the post_id on page matches the post_id posted. But I'm new to this and the only thing I can think of is.
if(!$row['post_id'] == $_GET['id']) {
}
I don't know what to make it do after. Also if anyone knows how or can help point me in the right direction that would be great. Thanks.
Here is the update of the total thing here. It still shows post it's already on. hope this helps. This is the php code for the page.
<?php
mysql_select_db($database_xxx, $xxx);
$result= mysql_query("SELECT COUNT(*) FROM news");
$total = mysql_result($result, 0, 0);
// create a random number
mt_srand((double)microtime()*1000000);
$number = mt_rand()%$total;
// get a random entry
$result= mysql_query(sprintf("SELECT * FROM news WHERE post_id <> %d LIMIT %d, 3", $post->post_id, $number));
$row = mysql_fetch_array($result);
?>
<?php
if (! isset($_GET['id']) || (int) $_GET['id'] === 0 ) {
echo "Incorrect input, aborting";
exit;
}
mysql_select_db($database_xxx, $xxx);
$sql = "SELECT * FROM news WHERE post_id = " . $_GET['id'];
// a line of debug to make sure things are as expected
$query = MYSQL_QUERY($sql);
// query your table for a match with post_id
if (mysql_num_rows($query) == "1")
// if a record is found, show the info
{
$fetch = mysql_fetch_array($query); // set $fetch to have the values from the table
} else {
echo "No match in database found."; // if no match is found, display this error
}
?>
Assuming that code is on the page where you view the main product:
$result= mysql_query(sprintf("SELECT * FROM news WHERE id <> %d LIMIT %d, 5", $post->id, $number));
Also, you should not be using mysql_* functions anymore as they are deprecated; checkout PDO
I have two tables in my database:
1) blog_table
2) content
In blog_table I have values called postID that may or may not match up to values called id in the table content. I am wanting to know how I can write a while loop or foreach loop that will cycle through content table and perform one action if the id equals the value of postID in the blog_table and perform a different action if it doesn't.
Right now I can only get id = postID
$blog_table = $_REQUEST['blog_table'];
$getblogtable = mysql_query("SELECT * FROM content WHERE type = '5' AND blogID = '{$_REQUEST['id']}' ORDER BY `order` ASC");
while ($row = mysql_fetch_assoc($getblogtable))
{
$getblogposts1 = mysql_query("SELECT postID FROM `$blog_table`");
while ($row1 = mysql_fetch_assoc($getblogposts1))
{
if( $row1['postID'] == $row['id']) {
echo "do something<br>";
}else{
echo "do something else<br>";
}
} echo "<p></p>";
}
[Edit based on OP's comments and revised question]
$getblogposts = mysql_query("SELECT * FROM content WHERE type = '5' AND blogID = '{$_REQUEST['id']}' ORDER BY `order` ASC");
while ($row = mysql_fetch_assoc($getblogposts))
{
$matches = mysql_query("SELECT * FROM $blog_table WHERE postID = $row['id']");
if (mysql_num_rows($matches) > 0)
{
// do something
}
else
{
// do something else
}
}
Regarding a different design, I can't say for sure that it's necessary, but I don't like running a loop of queries like this. I think one query should be enough to get everything you need in this case. Maybe if you describe your application, we could find a better query or more appropriate design.
Just providing an easier to see solution for you to your problem.
I suggest using inner joins which will solve the issue at hand.
For example, Something like:
SELECT * FROM content AS C INNER JOIN $blog_table AS B on B.postID = C.id
Here is a great introduction to joins (inner, left, right, full):
http://www.w3schools.com/sql/sql_join.asp
$blog_table = $_REQUEST['blog_table'];
$getblogtable = mysql_query("SELECT postID FROM `$blog_table`");
while ($row = mysql_fetch_assoc($getblogtable))
{
$postID = $row['postID'];
$getblogposts1 = mysql_query("SELECT * FROM content WHERE id = '$postID' ORDER BY `order` ASC");
while ($row1 = mysql_fetch_assoc($getblogposts1))
{
// if( $row1[id] == $postId )
// do something
// else
// do something else
}
}
I have an Ajax call to create an image gallery. There is a combo box to set the number of images per page, and pagination to navigate through the pages. It's working fine, except that if a person is on the last page, and they increase the number of images per page, it reloads to the current page number. This is a problem because there are now less pages and so the page is blank. In other words, you end up on page 7 of 5 for instance.
I reckon the problem is in the PHP as that is where the number of pages is calculated. I've thought out an if statement to deal with this:
if ($page > $no_of_paginations) {
$page = $no_of_paginations;
}
However, I don't know where to place this. The reason being, $page needs to be defined before the mysql_query, but $no_of_paginations is defined after the query.
Any thoughts on how I can make this functional?
I'll post the pertinent code below:
<?php
$page = 0;
if(isset($_GET['page'])){
$page = (int) $_GET['page'];
}
$cur_page = $page;
$page -= 1;
if((int) $_GET['imgs'] > 0){
$per_page = (int) $_GET['imgs'];
} else {
$per_page = 16;
}
$start = $per_page * $page;
include"db.php";
$query_pag_data = "SELECT `imgURL`,`imgTitle` FROM `images` ".
"ORDER BY `imgDate` DESC LIMIT $start, $per_page";
$result_pag_data = mysql_query($query_pag_data) or die('MySql Error' . mysql_error());
echo "<ul class='new_arrivals_gallery'>";
while($row = mysql_fetch_assoc($result_pag_data)) {
echo "<li><a target='_blank' href='new_arrivals_img/".$row['imgURL']."' class='gallery' title='".$row['imgTitle']."'><img src='new_arrivals_img/thumbnails/".$row['imgURL']."'></a></li>";
}
echo "</ul>";
/* --------------------------------------------- */
$query_pag_num = "SELECT COUNT(*) AS count FROM images";
$result_pag_num = mysql_query($query_pag_num);
$row = mysql_fetch_array($result_pag_num);
$count = $row['count'];
$no_of_paginations = ceil($count / $per_page);
?>
Thanks for your help!
As you are currently doing it, there would be no problem with moving the last section to above the main query.
A better way to find the total records with MySQL is to use the SQL_CALC_FOUND_ROWS keyword on your main query (so here it is SELECT SQL_CALC_FOUND_ROWS imgURL, imgTitle FROM images WHERE etc) then you can query SELECT FOUND_ROWS() and just get the number of records found in the last query. As well as being faster and more efficient, this avoids a race condition when records are added between the two queries.
However, in this case you should probably just do the two current queries in the reverse order as your only other option is to check at the end and repeat if necessary.
You should use query:
$query_pag_data = "SELECT SQL_CALC_FOUND_ROWS `imgURL`,`imgTitle` FROM `images` ".
"ORDER BY `imgDate` DESC LIMIT $start, $per_page";
And instead of
$query_pag_num = "SELECT COUNT(*) AS count FROM images";
use
$query_pag_num = "SELECT FOUND_ROWS()";
If you do the "SELECT COUNT(*) ..." query earlier in the script (at least before the other query), you will have $no_of_paginations earlier, and can use it to clamp $page to the correct range.
Sometimes you just have to bite the bullet and do a query twice. Accept the user-provided "I want page X" value, and try to get that particular page. If it ends up being past the end of the available data, you can either say "hey, wait... that ain't right" and abort, or redo the loop and default to the last available page.
while(true) {
$sql = "select sql_calc_found_rows .... limit $X,$Y";
$result = mysql_query($sql) or die(mysql_error());
$sql = "select found_rows();"; // retrieve the sql_calc_found_rows_value
$res2 = mysql_query($sql);
$row = mysql_fetch_array($res2);
$total_rows = $row[0];
if ($total_rows < $requested_row) {
... redo the loop and request last possible page ...
} else {
break;
}
}
details on found_rows() function here.