I'm using pagination for my search results but for some reason my pagination is not working correctly with my search script. I can't seem to find the correct place to put the LIMIT $start, $display in my search query code where ever I put it in my code it displays the pagination all wrong. Can some one please help me?
Here is the part of my PHP & MySQL search code.
$mysqli = mysqli_connect("localhost", "root", "", "sitename");
mysqli_select_db($mysqli, "sitename");
$search_explode = explode(" ", $search);
foreach($search_explode as $search_each) {
$x++;
if($x == 1){
$construct .= "article_content LIKE '%$search_each%' OR title LIKE '%$search_each%' OR summary LIKE '%$search_each%'";
} else {
$construct .= "OR article_content LIKE '%$search_each%' OR title LIKE '%$search_each%' OR summary LIKE '%$search_each%'";
}
}
$construct = "SELECT users.*, users_articles.* FROM users_articles
INNER JOIN users ON users_articles.user_id = users.user_id
WHERE $construct";
$run = mysqli_query($mysqli, $construct);
$foundnum = mysqli_num_rows($run);
SQL statement.
SELECT users.*, users_articles.* FROM users_articles INNER JOIN users ON users_articles.user_id = users.user_id WHERE article_content LIKE '%find%' OR title LIKE '%find%' OR summary LIKE '%find%'OR article_content LIKE '%this%' OR title LIKE '%this%' OR summary LIKE '%this%'OR article_content LIKE '%article%' OR title LIKE '%article%' OR summary LIKE '%article%' LIMIT 0, 10
The basic syntax of SELECT is:
SELECT [fields]
FROM [tables [JOIN tables]]
WHERE [conditions]
GROUP BY [fields]
HAVING [conditions]
ORDER BY [fields]
LIMIT [limit]
So, right at the end after the WHERE conditions.
Here's the documentation which shows the full syntax.
Are you remembering to insert spaces into your string snippets as you build the query? Remember that PHP doesn't put anything into a string that you don't put there yourself.
$x = 'a';
$x .= 'b';
gives you ab, not a[space]b. Your $construct will be full of syntax errors if more than one search term is entered, as the subsequent OR will be attached directly to the end of any previous added search terms. You'll end up with something like:
[...snip...] OR summary LIKE '%$search_each%OR article_content LIKE[...snip...]
^^--syntax error here.
The same applies if you append the limit clause without making sure there's a space between the end of your query and the "LIMIT X,Y" text you append.
This should show the first 10 rows:
SELECT users.*, users_articles.* FROM users_articles
INNER JOIN users ON users_articles.user_id = users.user_id
WHERE article_content LIKE '%something%'
LIMIT 0, 10
Changing the LIMIT clause to the following should display rows from 11 to 20:
LIMIT 10, 10
Also note that you should probably escape your $construct string as #Col. Shrapnel suggested in a comment above. This is to avoid SQL injection.
In addition, you may want to investigate using Full Text Indexing instead.
$mysqli = mysqli_connect("localhost", "root", "", "sitename");
mysqli_select_db($mysqli, "sitename");
$search_explode = explode(" ", $search);
foreach($search_explode as $search_each) {
$x++;
if($x == 1){
$construct .= " article_content LIKE '%$search_each%' OR title LIKE '%$search_each%' OR summary LIKE '%$search_each%'";
} else {
$construct .= " OR article_content LIKE '%$search_each%' OR title LIKE '%$search_each%' OR summary LIKE '%$search_each%'";
}
}
$construct = "SELECT users.*, users_articles.* FROM users_articles
INNER JOIN users ON users_articles.user_id = users.user_id
WHERE $construct";
$construct .= " LIMIT 0, 10" ; // replace 0, 10 with your variables
$run = mysqli_query($mysqli, $construct);
$foundnum = mysqli_num_rows($run);
Related
The following is the PHP code I am using for a simple search feature in my website.
The search simply shows refults if it matches the SQL column "tags".
I would like to add one more filter in the SQL query.
I want to filter the search results based on city.
The city data is already in the SQL, but I dont know how to add it here without breaking the properly working search funtion.
I tried $data_sql .= " AND city='newyork' "; after the 8th line, but it didnt work.
$name=str_replace(' ', '%', $_POST['query']);
$newsearch = "%$name%";
$base_sql = "SELECT %s FROM posts WHERE tags LIKE ?";
$count_sql = sprintf($base_sql, "count(*)");
$stmt = $connect->prepare($count_sql);
$stmt->execute([$newsearch]);
$total_data = $stmt->fetchColumn();
$data_sql = $count_sql = sprintf($base_sql, "*")." LIMIT ?,?";
$stmt = $connect->prepare($data_sql);
$stmt->execute([$newsearch, $start, $limit]);
$result = $stmt->fetchAll();
So your additional filter must be before LIMIT ?, ?
if you try adding it after the 8th line the query will look like this:
SELECT * FROM posts WHERE tags LIKE 'search' LIMIT 0, 100 AND city='newyork'
so what can you do:
$data_sql = sprintf($base_sql, "*");//we will add the limit before preparation
//don't know why do you need that $count_sql here
$data_sql .= " AND city='newyork' ";
//IF you need some GROUP BY do it here
//If you need some ORDER BY do it here
$data_sql .= " LIMIT ?, ?";
$stmt = $connect->prepare($data_sql);
$stmt->execute([$newsearch, $start, $limit]);
$result = $stmt->fetchAll();
The line $data_sql .= " AND city='newyork' "; won't work as it will add the string after the LIMIT which is not a valid sql query.
You should instead edit the line with the base_sql like this:
$base_sql = "SELECT %s FROM posts WHERE tags LIKE ? AND city='newyork'";
And of course if 'newyork' needs to be a variable you can do thr same thing like you did for the tags
First, let's add the new criteria:
$base_sql = "SELECT %s FROM posts WHERE tags LIKE ? and city = ?";
Then make sure that you pass the city as a parameter
$stmt->execute([$newsearch, 'newyork', $start, $limit]);
The following section of code is used to to filter data from an html page in real time from an SQL database using ajax. For some reason the condition in the SQL statement ignores the following condition samples_database.sample_storage != 'discarded' but it works in the second part of the else statement.
if(isset($_POST["query"])) {
$search = mysqli_real_escape_string($conn, $_POST["query"]);
$query .= "
SELECT * FROM samples_database JOIN storage_database on samples_database.storage_location=storage_database.id
WHERE samples_database.sample_storage != 'discarded'
AND samples_database.env_sam_id LIKE '%".$search."%'
OR samples_database.c_sam_id LIKE '%".$search."%'
OR samples_database.sample_type LIKE '%".$search."%'
OR storage_database.storage_name LIKE '%".$search."%'
ORDER BY samples_database.env_sam_id;";
} else {
$query .= "
SELECT * FROM samples_database JOIN storage_database on samples_database.storage_location=storage_database.id WHERE sample_storage != 'discarded' ORDER BY samples_database.env_sam_id;";
}
Can anybody help me this this silly problem please?
There's an order of precedence: AND is calculated before OR:
if(isset($_POST["query"])) {
$search = mysqli_real_escape_string($conn, $_POST["query"]);
$query .= "
SELECT * FROM samples_database JOIN storage_database on samples_database.storage_location=storage_database.id
WHERE samples_database.sample_storage != 'discarded'
AND (samples_database.env_sam_id LIKE '%".$search."%' OR
samples_database.c_sam_id LIKE '%".$search."%' OR
samples_database.sample_type LIKE '%".$search."%' OR
storage_database.storage_name LIKE '%".$search."%')
ORDER BY samples_database.env_sam_id;";
} else {
$query .= "
SELECT * FROM samples_database JOIN storage_database on samples_database.storage_location=storage_database.id WHERE sample_storage != 'discarded' ORDER BY samples_database.env_sam_id;";
}
In the else part you have only 1 condition:
sample_storage != 'discarded'
so it can't be "ignored".
But in the if part you have something like this:
A and B or C or D or E...
If one of C or D or E... is true then the result is true and you think that A is "ignored".
So make use of parentheses around each part that suits your needs.
maybe something like this:
A and (B or C or D or E...)
$query = "SELECT * FROM posts WHERE language='$lang' AND (title LIKE '%$search%' OR author LIKE '%$search%' OR year LIKE '%$search%')";
This does exactly what it should do. But what I'd like to do is having "title" as a priority. But as it looks now (every search is in a dropdown of html) it simple show's it without an priority. So the title can be at the very bottom, and the author at the top. Wrong order. I'd like to somehow always have the title at top.
How?
$output = '';
$lang = $_SESSION["lang"];
$search = $_POST["query"];
$query = "SELECT * FROM posts WHERE language='$lang' AND (title LIKE '%$search%' OR author LIKE '%$search%' OR year LIKE '%$search%')";
$result = mysqli_query($connect, $query);
$output = '<ul class="list-unstyled">';
if(mysqli_num_rows($result) > 0)
{
while($row = mysqli_fetch_array($result))
{
$output .= '<li>'.$row["book"].'</li>';
}
}
else
{
$output .= 'Not found.';
}
$output .= '</ul>';
echo $output;
You can split up the query.
$output = '';
$lang = $_SESSION["lang"];
$search = $_POST["query"];
$query2 = "SELECT * FROM posts WHERE language='$lang' AND title LIKE '%$search%'";
$result2 = mysqli_query($connect, $query2);
$output = '<ul class="list-unstyled">';
if(mysqli_num_rows($result2) > 0)
{
while($row = mysqli_fetch_array($result2))
{
$output .= '<li>'.$row["book"].'</li>';
}
}
else
{
$output .= 'Not found.';
}
$query = "SELECT * FROM posts WHERE language='$lang' AND (author LIKE '%$search%' OR year LIKE '%$search%')";
$result = mysqli_query($connect, $query);
if(mysqli_num_rows($result) > 0)
{
while($row = mysqli_fetch_array($result))
{
$output .= '<li>'.$row["book"].'</li>';
}
}
else
{
$output .= 'Not found.';
}
$output .= '</ul>';
echo $output;
ORDER BY should do the trick for you here:
http://www.w3schools.com/sql/sql_orderby.asp
$query = "
SELECT book
, title
, url
FROM posts
WHERE language='$lang'
AND (
title LIKE '%$search%'
OR
author LIKE '%$search%'
OR
year LIKE '%$search%'
)
ORDER BY title ASC
, author ASC
, book ASC
";
I've added an optional order by 'author' and 'book' too (the priority of ordering starts with 'title', then 'author' and finally 'book') - you can change this to whatever you need though in ASC (ascending) or DESC (descending) order.
I'd also recommend you consider using bind params rather than passing in variables directly into your SQL to prevent SQL Injection.
Mysqli Bind Param Documentation
http://php.net/manual/en/mysqli-stmt.bind-param.php
Really good SO post here with help and more info about SQL Injection
How can I prevent SQL injection in PHP?
Also - try to avoid using SELECT * FROM... where possible, and only SELECT out the information you need. You'll be able to INDEX it better this way too (meaning quicker retrieval of data from the database).
You could use a scoring system to give each match a score and then sort by the match score. So a match for title gets a higher score and a match for author gets the next highest and so on. I'll rewrite just the query here:
SELECT *,
(
CASE
WHEN title LIKE '%$search%' THEN 100
WHEN author LIKE '%$search%' THEN 10
WHEN year LIKE '%$search%' THEN 1
END
) AS matchScore
FROM posts
WHERE
language='$lang' AND
(title LIKE '%$search%' OR author LIKE '%$search%' OR year LIKE '%$search%')
ORDER BY matchScore DESC
I am creating a search engine whereby I require videos to be displayed according to the keywords input.
So for my codes, I have
$search_exploded = explode (" ", $search);
foreach($search_exploded as $search_each){
$x = 0;
$x++;
if($x>=1){
$construct ="keywords LIKE '%$search_each%'";
}
else{
$construct ="OR keywords LIKE '%$search_each%'";
}
$x = 0;
}
and
$query ="SELECT * FROM test WHERE $construct";
$runquery = mysql_query($query);
$foundnum = mysql_num_rows($runquery);
The problem lies in the $runquery as my the error i get from my browser states that the line $foundnum = mysql_num_rows($runquery); is returning a Boolean value instead of the supposed resource type value.
Can anyone help fix this? I'm stuck on this for quite some time now. Thankful for and appreciate any help!
there is a problem in if condition and every time you set $x to 0 , then why you init it.
$x = 0;
foreach($search_exploded as $search_each){
if($x==0){
$construct =" keywords LIKE '%$search_each%' ";
}else{
$construct .=" OR keywords LIKE '%$search_each%' ";
}
$x++;
}
Try this .
You have a couple of logical errors inside your foreach loop pertaining to the $x variable.
Here is a simple way to achieve what you are trying to do (without using some kind of flags like $x)-
$search_exploded = explode (" ", $search);
// An array for the `LIKE` conditions
$construct_list = [];
// Adding the conditions in the array
foreach($search_exploded as $search_each){
$construct_list[] = "keywords LIKE '%$search_each%'";
}
// Joining them using OR
$construct = implode(" OR ", $construct_list);
// Supposing there are no keywords, the
// WHERE should not exist. So make a separate var for that -
$where_clause = "";
if(trim($construct) != ""){
$where_clause = "WHERE $construct";
}
// Perform your query
$query ="SELECT * FROM test $where_clause";
Try this:
$search_exploded = explode (" ", $search);
$construct = '1';
if (!empty($search_exploded)) {
$construct = '';
foreach($search_exploded as $search_each){
$construct .= $construct == '' ? " keywords LIKE '%$search_each%'" : " OR keywords LIKE '%$search_each%'";
}
}
$query ="SELECT * FROM test WHERE $construct";
$runquery = mysql_query($query);
if ($runquery) {
$foundnum = mysql_num_rows($runquery);
}
You seem to try to omit the OR for the 2nd and subsequent runs around the loop, but keep it for the first. should be the other way round,.
But I would probably avoid using the loop, and just use implode. Something like this (although would need to escape the values before using them in the query).
$search_exploded = explode (" ", $search);
if (count($search_exploded) > 0)
{
$construct = implode("%' OR keywords LIKE '%", $search_exploded);
$query ="SELECT * FROM test WHERE keywords LIKE '%".$construct."%'";
$runquery = mysql_query($query);
$foundnum = mysql_num_rows($runquery);
}
I am new to codeigniter. I have done auto suggest search using simple mysql but not with codeigniter's active records. It's very confusing to me.
My mysql format was :
$s = $_POST['s'];
$search_result = explode(' ', $s);
$query_temp = '';
$i=0;
foreach($search_result as $search){
$i++;
if($i == 1){
$query_temp .= "title LIKE '%$search%' OR description LIKE '%$search%' OR keywords LIKE '%$search%' OR link LIKE '%$search%'";
}else{
$query_temp .= "OR title LIKE '%$search%' OR description LIKE '%$search%' OR keywords LIKE '%$search%' OR link LIKE '%$search%'";
}
}
$search_query = mysql_real_escape_string(htmlentities($_POST['s']));
$run = mysql_query("SELECT * FROM search WHERE $query_temp")or die(mysql_error());
But here I have to search from 3 tables. I have no idea how to do it in this format in codeigniter..
If field 'title' belongs to table 'a',
field 'description' belongs to table 'b'
and field 'keywords' belongs to table 'c' then you can use like this :
$this->db->select('*');
$this->db->from('a, b, c');
$this->db->like(a.title, $search);
$this->db->or_like(b.description, $search);
$this->db->or_like(c.keywords, $search);
$query = $this->db->get();