I have a problem with queries that contains ' in names.
Select HTML:
<select id="list-skins" name = "specific_skins_list[]" multiple="multiple" style="width: 500px">
<?php
$get_all_skins_list= mysqli_query($conn, "SELECT * FROM skins_list");
while($row = mysqli_fetch_array($get_all_skins_list)) {
$skins_name = $row["skins_list"];
$skins_id = $row["id"];
$skins_name = str_replace("'", "’", $skins_name);
echo '<option value="'.$skins_name.'">'.$skins_name.'</option>';
}//END WHILE GET_ALL_REGIONS
?>
</select>
POST
if (isset($_POST["specific_skins_list"])) {
$query .= "
AND skins LIKE '%" . implode("%' or skins LIKE '%", $_POST['specific_skins_list']) ."%'
";
}
My problem is: in table skins_list, I have names like:
i'oan , v'asilivev etc...
These names contain a ' .
The query works fine if the names are normal without special characters. I found couple solutions in my search to use mysqli_real_escape_string.
I tried to do something like this:
if (isset($_POST["specific_skins_list"])) {
$skins = mysqli_real_escape_string($conn,$_POST["specific_skins_list"]) ;
$query .= "
AND skins LIKE '%" . implode("%' or skins LIKE '%", $skins) ."%'
";
}
but I get this error:
mysqli_real_escape_string() expects parameter 2 to be string, array given in... my page
And the query is like this :
SELECT *
FROM import_acc
WHERE available = 'YES' AND region = 'UVAS' AND st= 'Truex' AND skins LIKE '%%' "
Thank you for your time.
P.S. I think the only way i can fix this is to modified all table skins_list and add manulaly double '' to every name :D
You defined the fields as "specific_skins_list[]", so it produces an array instead of a string, and that's why you get the error. mysqli_real_escape_string only works on strings.
The simplest way to solve this is to loop on this array, calling mysqli_real_escape_string on each element, e.g:
$skins = [];
foreach($_POST["specific_skins_list"] as $skin)
$skins[] = mysqli_real_escape_string($conn,$skin);
Now your $skins variable contains properly formatted strings for an SQL query (probably).
Of course, in a real script you should do a lot more validation - you should make sure that $_POST["specific_skins_list"] is defined and is indeed an array (using isset and is_array), and that each element is a valid skin name or something (e.g. using preg_match).
Otherwise your script may generate lots of errors or your DB can be hacked if someone uses the script directly, bypassing your UI.
Related
I have looked for answers here in the community but I could not find anything specific. I have this page where I can search the name of users previously registered in my MySQL database. I am currently using the following statements:
PHP: $value = str_replace(' ', '%', $search);
SQL: "select * from user where name like '%".$value."%' order by name asc;"
The $search variable comes from a search form on this same page. (The above code allows me to make queries with more than one value). For example, considering a user named Luiz Henrique da Silva, if I search for Luiz, Luiz Henrique, or even Luiz Silva, this code will work perfectly, listing that user.
But my problem is: if I search the name out of order, such as Silva Henrique, or Silva Luiz, the user will not be listed. How could I enable this reverse search in a simple way?
Please note, using this code I am able to search separate values, thus my need is to make queries using disordered values!
PHP:
$value = str_replace(" ", "%' and name like '%", $search);
So using each word separately. But not safe: sql injection.
Using preg_replace caters for consecutive spaces:
$value = preg_replace('/\s+/', "%' and name like '%", $search);
$search = 'Jobs Steve';
$search = mysql_real_escape_string($search);
$where_condition = '';
$search_arr = explode(' ', $search);
foreach($search_arr as $key => $name) {
if ($where_condition != '') $where_condition .= ' AND ';
$where_condition .= " name LIKE '%$name%' ";
}
$sql = "SELECT * FROM user WHERE $where_condition ORDER BY name ASC;";
$sql will be like a SELECT * FROM user WHERE name LIKE '%Jobs%' AND name LIKE '%Steve%' ORDER BY name ASC;
It's a bad idea to inject unsanitized user input directly into a query because someone can execute their own queries and compromise your data/security. Look into prepared statements: http://php.net/manual/en/mysqli.quickstart.prepared-statements.php.
As for your question, you could take the search that was provided, for example: Luiz Henrique, break it apart by whitespace so you get "Luiz" and "Henrique", then create a statement that looks something like:
WHERE name LIKE '%Luiz%' AND name LIKE '%Henrique%'
In this way you just keep adding AND LIKE statements for each individual component.
I try to make a search engine for profiles, but I stock with an error that "Division by zero" and and after I used var_dump(mysql_error()) it shows me "Query was Empty".
here is my query and php code:
$search_rs = dbq('SELECT * FROM users WHERE fname LIKE '%$_GET[query]%' LIMIT 0, OR fname LIKE '%$_GET[query]%'');
if($search_rs == false) {
var_dump(mysql_error());
}
elseif (db_num($search_rs) > 0) {
while ($results = db_next($search_rs)) {
echo('<li>
<a class="avatar" href="http://mysite/'.$results['pagekey'].'" target="_blank">
<img src="'.thumbnail($results['avatar'], 64, 64).'" />
</a>
<div class="info">
<a href="http://profiler.ir/'.$results['pagekey'].'" target="_blank">
<span class="fullname">'.$results['pre_name'].' '.$results['fname'].' '.$results['lname'].'</span>
</a>
</div>
</li> ');
}
}
else echo "not found !!!";
BUT When I remove LIKE '%$_GET[query]%'and make a simple query without LIKE , it return results.
Change your query from this:
'SELECT * FROM users WHERE fname LIKE '%$_GET[query]%' LIMIT 0, OR fname LIKE '%$_GET[query]%''
To this:
"SELECT * FROM users WHERE fname LIKE '%" . $_GET['query'] . "%'"
The issues you had were:
Using single quotes for the whole query string as well as the LIKE '%…%' values inside of them. So using double quotes now, concatenating the values.
You also had missing single quotes for your $_GET[query] so those are changed to $_GET['query'].
The placement of LIMIT 0, makes no sense so that is gone.
Also unsure why you had two fname LIKE '%" . $_GET['query'] . "%' in there. Removed the second one.
If you somehow need the LIMIT then this query should work:
"SELECT * FROM users WHERE fname LIKE '%" . $_GET['query'] . "%' LIMIT 0,100"
But I am just presuming you need 100 items, so change that 100 as well as the 0 offset to best match your needs.
The MySQL error is caused by malformed SQL text. The problem in the code is that the desired SQL text isn't being produced, due to the PHP syntax for interpreting/concatenating strings.
I recommend you use double quotes around the literal portions of the string, and use a dot operator to signify concatenation.
I also recommend you do the string manipulation as a separate step, so that the SQL text is available for inspection/debugging.
I also strongly recommend you use the mysql_real_escape_string function to reduce SQL injection vulnerabilities (when including user supplied data within the SQL text).
As an example:
$sql = "SELECT * FROM users WHERE fname LIKE '%" . mysql_real_escape_string($_GET[query]) . "%'";
#vardump($sql); # for inspecting/debugging issues with generating SQL text
$search_rs = dbq($sql);
Little Bobby Tables XKCD Exploits of a Mom
I'm trying to retrieve all the data id from a database where their tags(array) is like a given value.
This is what I have done so far...
$new_string = 'nice phone';
$construct = mysql_query("SELECT tag_array, name, id FROM details
WHERE tag_array LIKE $new_string%")
or die("<p>died 20: $construct<br>" . mysql_error());
while($getThis = mysql_fetch_array($construct)){
echo $getThis['id'].'<br />';
echo stripslashes($getThis['name']).'<br />';
}
It doesn't work ATALL.
Could you please point me to the right direction?
I'm really struggling!!
You should put $new_string in quotes.
NOTE It is very bad practice and you should always escape all variables you are passing to SQL. You should really read up on SQL injection and other security issues.
Also if you want to match $new_string anywhere in tag_array (which you most likely want), you need to add dollar sign in front of it too. You can read up more at MySQL reference manual.
So in the end:
"SELECT tag_array, name, id FROM details WHERE tag_array LIKE '%" . mysql_real_escape_string($new_string) . "%'"
You should sanitise the data before putting it in the query like:
$new_string = "blah...; DROP TABLE tag_array; #";
$sql = mysql_real_escape_string($new_string);
$sql = "SELECT tag_array, name, id FROM details WHERE tag_array LIKE %'$sql'%"
This is not enough though it just helps preventing sql inject, consider using regular expressions to clean the data. If you don't yet know about regexp check out this site: regexp info. It helped me mutch.
Basically i want to add wildcards to the the col value when searching...
Usually I do this the other way around like this:
WHERE cakes.cake_name LIKE '%$cake_search%'
however now i want it to match the inverse:
the user searches for 'treacle
sponge', i want this to match a row
where the cake_name column =
'sponge'.
is this possible?
WHERE '$cake_search' LIKE concat('%',cakes.cake_name, '%')
should work. It will need a full table scan but so will the inverse query. Have you looked into full text search for MySQL? It will likely make this sort of query more efficient.
Why not using MATCH?
MATCH(`cake_name`) AGAINST ('treacle sponge')
You would have to split the user supplied input on the space character and dynamically construct your query to check the column for those values:
$input = "treacle sponge";
$input_words = explode(' ', $input);
$sql_where = "WHERE cakes.cake_name IN('" . implode("','", $input_words) . "')"; // generates: WHERE cakes.cake_name IN('treacle','sponge')
In order to prevent SQL-Injection, I suggest using prepared statements.
$prepStmt = $conn->prepare('SELECT ... WHERE cakes.cake_name LIKE :cake_search
');
if($prepStmt->execute(array('cake_search'=>"%$cake_search%"))) {
...
}
Or, using full text search:
$prepStmt = $conn->prepare('SELECT ... WHERE MATCH (`cake_name`) AGAINST (:cake_search IN BOOLEAN MODE)');
if($prepStmt->execute(array('cake_search'=>$cake_search_words))) {
...
}
See JSON specialchars JSON php 5.2.13 for a complete example.. ;)
Right now I'm just using a simple
WHERE name LIKE '%$ser%'
But I'm running into an issue - say the search is Testing 123 and the "name" is Testing, it's not coming back with any results. Know any way to fix it? Am I doing something wrong?
If you want to search for 'Testing' or '123' use OR:
WHERE (name LIKE '%Testing%' OR name LIKE '%123%')
Note however that this will be very slow as no index can be used and it may return some results you didn't want (like "4123"). Depending on your needs, using a full text search or an external database indexing product like Lucene might be a better option.
That's how LIKE works - it returns rows that completely contain the search string, and, if you use "%" optionally contain something else.
If you want to see if the field is contained in a string, you can do it this way:
SELECT * FROM `Table` WHERE "Testing 123" LIKE CONCAT("%",`name`,"%")
As Scott mentioned, you cannot check to see if the search contains the column value, it works the other way round.
so if $ser = "testing" and table has a row name = testing 123 it will return
For what you're trying to do you'll need to tokenize the search query into terms and perform an OR search with each of them or better still check out mysql full text search for a much better approach
After the variable $ser is replaced, the query is:
WHERE name LIKE '%Testing 123%'
You should build the query separating by words:
WHERE name LIKE '%$word[1]%$word[2]%'
not efficient (as your example) but working as you want:
WHERE name LIKE '%$ser%' OR '$ser' LIKE CONCAT('%', name, '%')
As mentioned by Mark and others, a full text search method may be better if possible.
However, you can split the search string on word boundary and use OR logic—but check for the whole string first, then offer the option to widen the search:
NOTE: Input sanitization and preparation not shown.
1. Query with:
$sql_where = "WHERE name LIKE '%$ser%'";
2. If zero results are returned, ask user if they would like to query each word individually.
3. If user requests an 'each word' search, query with:
$sql_where = get_sql_where($ser);
(Working) Example Code Below:
$ser = 'Testing 123';
$msg = '';
function get_sql_where($ser){
global $msg;
$sql_where = '';
$sql_where_or = '';
$ser = preg_replace("/[[:blank:]]+/"," ", trim($ser)); //replace consecutive spaces with single space
$search_words = explode(" ", $ser);
if($search_words[0] == ''){
$msg = 'Search quested was blank.';
}else{
$msg = 'Search results for any of the following words:' . implode(', ', $search_words);
$sql_where = "WHERE name LIKE '%$ser%'";
foreach($search_words as $word){
$sql_where_or .= " OR name LIKE '%$word%'";
}
}
return $sql_where . $sql_where_or;
}
$sql_where = get_sql_where($ser);
//Run query using $sql_where string