I have created an auto suggestion search box using php and jquery. The user prompted to insert name and surname to find someone that exists in my database, in a table called user. Table users holds 2 columns, name and surname. My search works fine when you type the name but after pressing space to move and type surname does not give any results. The whole problem seems to appear when pressing space button. Any idea how to fix it?
This is my jquery code:
$(document).ready(function(){
$('#search_form_1').keyup(function(){
var value = $(this).val();
if(value != ''){
$('#search_result').show();
$.post('search_form.php', {value: value}, function(data){
$('#search_result').html(data);
});
}else{
$('#search_result').hide();
}
});
});
And this is my php code:
<?php
if(isset($_POST['value'])== true && empty($_POST['value']) == false){
$value = mysql_real_escape_string($_POST['value']);
$query = mysql_query(" SELECT `surname`, `name` FROM `users` WHERE (`surname` LIKE '$value%' OR `name` LIKE '$value%') OR (`name` LIKE '$value%' OR `surname` LIKE '$value%') ");
while($run = mysql_fetch_array($query)){
$surname = $run['surname'];
$name = $run['name'];
echo " $surname $name ";
}
}
?>
You have to split the search:
<?php
if(isset($_POST['value'])== true && empty($_POST['value']) == false){
$value = mysql_real_escape_string($_POST['value']);
$name_and_surname = explode(" ", $value);
$name = $name_and_surname[0];
$surname = $name_and_surname[1];
$q = " SELECT `surname`, `name` FROM `users` WHERE (`surname` LIKE '$name%' OR `name` LIKE '$name%') OR (`name` LIKE '$surname%' OR `surname` LIKE '$surname%') ";
// check your query one more time
echo $q;
$query = mysql_query($q);
while($run = mysql_fetch_array($query)){
$surname = $run['surname'];
$name = $run['name'];
echo " $surname $name ";
}
}
An edit is not granted so here is the code:
$value = mysql_real_escape_string($_POST['value']);
$names = explode(" ", $value);
if(count($names)>1){
$name = $names[0];
$surname = $names[1];
$q = "SELECT surname, name FROM users WHERE (name LIKE '$name%' AND surname LIKE '$surname%') OR (name LIKE '$surname%' AND surname LIKE '$name%')";
}else{
$q = "SELECT surname, name FROM users WHERE (name LIKE '$value%' OR surname LIKE '$value%')";
}
If you just want to amend the SQL query, you should just be able to do something like this.
select name, surname from users where CONCAT(name, ' ', surname) like '%value%'
That will take the first name and last name and put a space between them and then search that.
That means when your user hits the space bar it will still find the user you're looking for.
Related
I am trying to search from a table of employees from a form with 5 fields. The user can use any or all of the search fields with the following rules:
USERFORM (html/php)
EID: (textbox, exact match)
First name: (textbox, LIKE %fname%)
Last Name: (textbox, LIKE %lname%)
Email: (textbox, LIKE %email%)
Department: (dropdown, exact match)(includes a default value for not selecting amongst <options>)
The problem I am having is that when I search for firstname = %j%, it correctly filters to all employees with a firstname containing a j. However whenever I combine this with another or more search parameters it brings the maximum amount of results, rather than filtered minimum, for example firstname %j%, lastname, %b%. Will still return Joe bloggs, and joe coggs.
Same as if I were to add a department on there, I would like it to give me people with a j in their first name, a b in their last name who are a member of department 1. But instead then, it would give me all employees who are in the department regardless of the name search parameters, aswell as employees who are in another department bu have a j in their name.
And here is the query and other code:
$eid = $_POST['eid'];
$p_fname = $_POST['fname'];
$p_lname = $_POST['lname'];
$p_email = $_POST['email'];
$depid = $_POST['depid'];
if(empty($_POST['fname'])) { $fname = "";} else { $fname = "%$p_fname%"; }
if(empty($_POST['lname'])) { $lname = "";} else { $lname = "%$p_lname%"; }
if(empty($_POST['email'])) { $email = "";} else { $email = "%$p_email%"; }
$query = $db->prepare("SELECT `employees`.`eid`, `employees`.`fname`, `employees`.`lname`, `employees`.`dob`, `employees`.`email`, `departments`.`depname`
FROM `employees`
INNER JOIN `departments`
ON `employees`.`depid` = `departments`.`id`
WHERE
`eid` = :eid ||
`fname` LIKE :fname ||
`lname` LIKE :lname ||
`email` LIKE :email ||
`depid` = :depid
ORDER BY `employees`.`eid` ASC
LIMIT :start_from, 10");
$query->bindParam(":eid", $eid);
$query->bindParam(":fname", $fname);
$query->bindParam(":lname", $lname);
$query->bindParam(":email", $email);
$query->bindParam(":depid", $depid);
$query->bindParam(":start_from", $start_from);
$query->execute();
When I think about it I get why it would return the maximum results, however I have tried to change the OR to AND and used parentheses I get no results at all, because the the query is trying to return records that have a blank value in the columns which aren't defined.
I have also tried having AND for the exact values and OR for the wildcard values and this returns all results.
I really don't want to write a php script which has to define which columns to use and execute a different query for each scenario.
I recommend not adding needless logic to the WHERE clause. Build the dynamic statement and deliver the variables into the execute() call <- this is one of the very handy things about PDO.
$conditions = [];
$params = [];
if (!empty($_POST['eid']) {
$conditions[] = "eid = ?";
$params[] = $_POST['eid'];
}
if (!empty($_POST['fname']) {
$conditions[] = "fname LIKE ?";
$params[] = "%{$_POST['fname']}%";
}
if (!empty($_POST['lname']) {
$conditions[] = "lname LIKE ?";
$params[] = "%{$_POST['lname']}%";
}
if (!empty($_POST['email']) {
$conditions[] = "email LIKE ?";
$params[] = "%{$_POST['email']}%";
}
if (!empty($_POST['depid']) {
$conditions[] = "depid = ?";
$params[] = $_POST['depid'];
}
$params[] = $start_from;
Then apply the conditions to the sql string, and execute the prepared statement with the values bound to the placeholders.
$sql = "SELECT employees.eid,
employees.fname,
employees.lname,
employees.dob,
employees.email,
departments.depname
FROM employees
INNER JOIN departments ON employees.depid = departments.id
" . ($conditions ? 'WHERE ' . implode(" AND ", $conditions) : '') . "
ORDER BY employees.eid
LIMIT ?, 10";
$query = $db->prepare($sql);
$query->execute($params);
Here is a similar answer without the battery of conditionals:
Build SELECT query with dynamic number of LIKE conditions as a mysqli prepared statement
I solved the issue by using LIKE and not = as the operator for, and swapping OR for AND as mentioned in the mentioned in the comment on the question.
The reason I had to use LIKE was because when the field is not in use from the form, it has to be a wildcard, and so = isn't suitable.
$p_eid = $_POST['eid'];
$p_fname = $_POST['fname'];
$p_lname = $_POST['lname'];
$p_email = $_POST['email'];
$p_depid = $_POST['depid'];
// wildcard added when field not in use, but removed when in use
if(empty($_POST['eid'])) { $eid = "%%";} else { $eid = "$p_eid"; }
if(empty($_POST['fname'])) { $fname = "%%";} else { $fname = "%$p_fname%"; }
if(empty($_POST['lname'])) { $lname = "%%";} else { $lname = "%$p_lname%"; }
if(empty($_POST['email'])) { $email = "%%";} else { $email = "%$p_email%"; }
// wildcard added when field not in use, bu removed when in use
if(empty($_POST['depid'])) { $depid = "%%";} else { $depid = "$p_depid"; }
$query = $db->prepare("SELECT `employees`.`eid`, `employees`.`fname`, `employees`.`lname`, `employees`.`dob`, `employees`.`email`, `departments`.`depname`
FROM `employees`
INNER JOIN `departments`
ON `employees`.`depid` = `departments`.`id`
WHERE
`eid` LIKE :eid AND
`fname` LIKE :fname AND
`lname` LIKE :lname AND
`email` LIKE :email AND
`depid` LIKE :depid
ORDER BY `employees`.`eid` ASC
LIMIT :start_from, 10");
$query->bindParam(":eid", $eid);
$query->bindParam(":fname", $fname);
$query->bindParam(":lname", $lname);
$query->bindParam(":email", $email);
$query->bindParam(":depid", $depid);
$query->bindParam(":start_from", $start_from);
$query->execute();
I am having some trouble displaying text from database using PHP and SQL. Below is a script similar to what I have.
$search_split = explode(" ", $search); //$search is what user entered
foreach ($search_split as $searcharray) {
$searched = mysqli_query($connect, "SELECT * FROM people WHERE `description` LIKE '%$searcharray%'");
while($info = mysqli_fetch_array($searched)) {
echo $info['description'];
}
}
So, for example the user enter 'He is male'. I split the word into three part 'He', 'is' and 'male' using 'explode' function. After that, I search the database for words that is similar to those three word. However, if a row have all the three words, it would display the row three times. How can I make it to display only once?
You could do something like this:
$search = 'test search me';
$search_split = array_map(function($piece) use ($mysqli_connection){
return "'%" . $mysqli_connection->real_escape_string($piece) . "%'";
}, explode(' ', $search)); //$search is what user entered
$search_split = implode(' OR `description` LIKE ', $search_split);
$sql = "SELECT * FROM people WHERE `description` LIKE $search_split";
echo $sql; // SELECT * FROM people WHERE `description` LIKE '%test%' OR `description` LIKE '%search%' OR `description` LIKE '%me%'
$searched = mysqli_query($connect, $sql);
Can you use full text search?
Add a full text index to the table
ALTER TABLE people ADD FULLTEXT(description);
Then you can use a query like this
SELECT *
FROM people
WHERE
MATCH ( description )
AGAINST ('+He +is +male' IN BOOLEAN MODE)
First store your results into one array then display it. Refer below code.
$search_split = explode(" ", $search); //$search is what user entered
foreach ($search_split as $searcharray) {
$searched = mysqli_query($connect, "SELECT * FROM people WHERE `description` LIKE '%$searcharray%'");
while($info = mysqli_fetch_array($searched)) {
$results[$info['YOUR_PRIMARY_KEY']] = $info['description']; // this will over write your previous record
}
}
foreach($results as $result){
echo $result;
}
Now every records display only once.
You have put your db query in a foreach loop, which loops 3 times (with the current data: he, is and male). What you want to do is put all the search variables in one query, something like:
$search_split = explode(" ", $search); //$search is what user entered
$querypart = "'%" . implode("%' AND '%", $search_split) . "%'"; // use OR or AND, to your liking
$searched = mysqli_query($connect, "SELECT * FROM people WHERE `description` LIKE " . $querypart);
while($info = mysqli_fetch_array($searched)) {
echo $info['description'];
}
This does not take any escaping/sanitizing of the query input, be aware...
$result = array();
$search_split = explode(" ", $search); //$search is what user entered
foreach ($search_split as $searcharray) {
$searched = mysqli_query($connect, "SELECT * FROM people WHERE `description` LIKE '%$searcharray%'");
while($info = mysqli_fetch_array($searched)) {
$result[] = $info['description'];
}
}
$finalres = array_unique($result);
so, finalres contains unique results
for($i = 0; $i < count($finalres); $i++)
echo $finalres[$i];
I have 3 tables i want to access with my search php. 2 of them contain all the users profile information. One is called cprofile and the other is bprofile. they are both linked to a user table that contains the username, email, password and most importantly the profile picture.
With the search engine i am trying to access both the info from the search to the individual profile tables and to gather the account information from the user table. This is my code for searching for both types of users:
$search_output = "";
if( isset($_POST['searchquery']) && $_POST['searchquery'] != "" ) {
$searchquery = preg_replace('#[^a-z 0-9?!]#i', '', $_POST['searchquery']);
if($_POST['filter1'] == "Whole Site") {
$sqlCommand = "(SELECT count(*) FROM cprofile WHERE firstname ='%".$searchquery."%' OR lastname ='%".$searchquery."%')
UNION (SELECT count(*) FROM bprofile WHERE cname ='%".$searchquery."%')";
$query = mysqli_query( $db_conx, $sqlCommand ) or die( mysqli_error($db_conx) );
$count = mysqli_num_rows( $query );
while( $row = mysqli_fetch_array($query, MYSQLI_ASSOC) ) {
$userid = $row["userID"];
$ret = mysqli_query($db_conx, "SELECT id, username FROM users WHERE id='$userid'");
while($raw = mysqli_fetch_array($ret, MYSQLI_ASSOC)) {
$username = $raw['username']; $file= $raw['avatar'];
}
}
}
}
Does anyone notice where i am going wrong and how i could resolve this issue? Thanks in advance
I might be going in the wrong direction here but you are getting counts from your query and then looking for a userID in the while loop. If you want both then do something like
$sqlCommand = "
(SELECT userid, count(*) as count FROM cprofile WHERE firstname ='%".$searchquery."%' OR lastname ='%".$searchquery."%')
UNION
(SELECT userid, count(*) as count FROM bprofile WHERE cname ='%".$searchquery."%')
";
I have 3 search boxes and the user can type information into any 3 or all 3 search boxes.
$user = $_POST['user'];
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$query = "SELECT user.user, user.firstname, user.lastname
FROM user WHERE type = 'Owner' AND user LIKE '%$user%'";
If the person was search all 3, how would I put these into it?
$query = "SELECT user.user, user.firstname, user.lastname
FROM user WHERE type = 'Owner' AND user LIKE '%$user%'
OR/AND type = 'Owner' AND fname LIKE '%$firstname%'
OR/AND type = 'Owner' AND lname LIKE '%$lastname%'";
This is what I have but does not work properly but I need something like OR/AND etce etc... Can someone please advise me how to do it? Thanks
This will combine the WHERE statements if values are given
$user = mysql_real_escape_string($_POST['user']);
$firstname = mysql_real_escape_string($_POST['firstname']);
$lastname = mysql_real_escape_string($_POST['lastname']);
$where[] = "type='Owner'";
if(strlen($user) > 0){
$where[] = "user LIKE '%$user%'";
}
if(strlen($firstname) > 0){
$where[] = "firstname LIKE '%$firstname%'";
}
if(strlen($lastname) > 0){
$where[] = "lastname LIKE '%$lastname%'";
}
$query = "SELECT user.user, user.firstname, user.lastname
FROM user WHERE ". implode(' AND ', $where);
I have this right now:
if(isset($_POST["search"]) && !empty($_POST["search"])) {
$full_name = mysql_real_escape_string($_POST["search"]);
$sex = mysql_real_escape_string($_POST["sex"]);
list($firstname, $lastname) = array_map('ucfirst', explode(' ', $full_name));
$query = "SELECT firstname, lastname, id, user_name, sex, last_access, bostadsort FROM users WHERE (firstname LIKE '$firstname' OR lastname LIKE '$lastname') AND sex = '$sex'";
$result1 = mysql_query($query) or die(mysql_error());
$count = mysql_num_rows($result1);
while($get = mysql_fetch_array ($result1)){
echo $get["firstname"] . " " .$get["lastname"]."<br>";
}
}
This is my search query. Now the form is called "Search for full names". You type in, and then it splits to $firstname , $lastname.
Works great, no problems.
Although if you ONLY enter a userĀ“s LASTNAME, because maybe you dont remember the users firstname, then this code will take it as a firstname, because all before a space is firstname (list() line), and puts it in $firstname and will result nothing, as there's no firstname with that lastname.
How can i solve this? If you search by firstname it works fine, full name too, but not only lastname. Any smart solution?
If I understand correctly, this is the simplest solution:
list($firstname, $lastname) = array_map('ucfirst', explode(' ', $full_name, 2));
if (!$lastname) $lastname = $firstname;
Edit: Added a limit to the explode line.
You can build a series of conditions:
Split the input on space
For each item in the resulting array, append OR firstname='value' OR lastname='value'
So smith becomes:
SELECT * FROM table WHERE (firstname='smith' OR lastname='smith') ....
And john smith becomes:
SELECT * FROM table WHERE (firstname='john' OR lastname='john' OR firstname='smith' OR lastname='smith') ....
If that's not to your liking then you can break out the search terms so you can enter first and last name separately.
Search for both(or more) list items, since names may contain spaces and look for unique results.
$arr_name= explode(' ', $full_name);
foreach($arr_name as $name){
$query = "SELECT firstname, lastname, id, user_name, sex, last_access, bostadsort FROM users WHERE (firstname LIKE '$name' OR lastname LIKE '$name') AND sex = '$sex'";
$result1 = mysql_query($query) or die(mysql_error());
...
}
if (!empty($_POST["search"])) {
$name = mysql_real_escape_string($_POST["search"]);
$sex = mysql_real_escape_string($_POST["sex"]);
$query = "SELECT firstname, lastname, id, user_name, sex, last_access, bostadsort
FROM users
WHERE (firstname = '$name'
OR lastname = '$name'
OR CONCAT(firstname, lastname) = '$name'
OR CONCAT(lastname, firstname) = '$name')
AND sex = '$sex'";
$result1 = mysql_query($query) or die(mysql_error());
$count = mysql_num_rows($result1);
while ($get = mysql_fetch_array($result1)){
echo $get["firstname"] . " " . $get["lastname"] . "<br>";
}
}
I simply check whether it the search input is the first name, the last name, both first name and last name or both last name and first name.
PS: A nice side affect of this version is that it will find names like Milhouse van Houten, too. Your original version (and many of the here proposed ones) couldn't deal with this case. They would look for Milhouse and van.
PPS: You probably chose a *_ci collation for the database. Thus string comparison will be case-insensitive: You don't need to ucfirst.