Correct way to use LIKE '%{$var}%' with prepared statements? - php

This does not work
$sql = 'SELECT * FROM `users` WHERE username LIKE \'%{?}%\' ';
Warning: mysqli_stmt::bind_param(): Number of variables doesn't match number of parameters in prepared statement in /home/rgero/public_html/php/searchadmins.php on line 1
This one doesn't work either
$sql = 'SELECT * FROM `users` WHERE username LIKE %{?}% ';
Fatal error: Wrong SQL: SELECT * FROM users WHERE username LIKE %{?}% Error: 0 in /home/rgero/public_html/php/searchadmins.php on line 1
How would I go about this? I'm trying to make a search for players function that updates the results as you're typing in the form, something like how google already shows answers while you're typing. I need for the username Admin , if you type dm, to show it already among other usernames that contain "dm". It should also be case insensitive

Try this
$likeVar = "%" . $yourParam . "%";
$stmt = $mysqli->prepare("SELECT * FROM REGISTRY where name LIKE ?");
$stmt->bind_param("s", $likeVar);
$stmt->execute();
you need to prepare the query using simply ? then you bind the param using bind_param.

Related

Error when trying to select from a database table where user_id = $_SESSION['id']

I've seen that there are many posts about this error, but I can't find an answer for my particular problem. I'm trying to show a table for the user, but only if is logged in, and only if the table row is added by that particular user.So, i'm trying tu use this line:
$sql = "SELECT * FROM data WHERE id_user = $_SESSION['id']";
$result = mysqli_query($connect, $sql);
And I get this error:
" syntax error, unexpected '' (T_ENCAPSED_AND_WHITESPACE), expecting
'-' or identifier (T_STRING) or variable (T_VARIABLE) or number
(T_NUM_STRING)"
Also, i tried
$sql = "SELECT * FROM 'data' WHERE 'id_user' = '$_SESSION['id']'";
Note the ' ' around table name and variables
What to change so that the syntax is good?
Don't do it like that, use a prepared statement:
$sql = "SELECT * FROM data WHERE id_user = ?";
$stmt = mysqli_prepare($link, $sql);
mysqli_stmt_bind_param($stmt, "i", $_SESSION['id']);
mysqli_stmt_execute($stmt);
More info can be found here: https://secure.php.net/manual/en/mysqli.prepare.php
It takes some getting used to, and it might be a little more verbose (you could wrap that in your own class or functions), but it will be vastly safer and more portable.
Not to mention you can brag to your friends that you use prepared statements by default!
change your query as:
$sql = "SELECT * FROM data WHERE id_user = ". $_SESSION['id'];
This may work for you as of now, but you have to change your query as your query is open for SQL injection.
Use prepared statement to build your query.

Using PHP variable in SQL query

I'm having some trouble using a variable declared in PHP with an SQL query. I have used the resources at How to include a PHP variable inside a MySQL insert statement but have had no luck with them. I realize this is prone to SQL injection and if someone wants to show me how to protect against that, I will gladly implement that. (I think by using mysql_real_escape_string but that may be deprecated?)
<?php
$q = 'Hospital_Name';
$query = "SELECT * FROM database.table WHERE field_name = 'hospital_name' AND value = '$q'";
$query_result = mysqli_query($conn, $query);
while ($row = mysqli_fetch_assoc($query_result)) {
echo $row['value'];
}
?>
I have tried switching '$q' with $q and that doesn't work. If I substitute the hospital name directly into the query, the SQL query and PHP output code works so I know that's not the problem unless for some reason it uses different logic with a variable when connecting to the database and executing the query.
Thank you in advance.
Edit: I'll go ahead and post more of my actual code instead of just the problem areas since unfortunately none of the answers provided have worked. I am trying to print out a "Case ID" that is the primary key tied to a patient. I am using a REDCap clinical database and their table structure is a little different than normal relational databases. My code is as follows:
<?php
$q = 'Hospital_Name';
$query = "SELECT * FROM database.table WHERE field_name = 'case_id' AND record in (SELECT distinct record FROM database.table WHERE field_name = 'hospital_name' AND value = '$q')";
$query_result = mysqli_query($conn, $query);
while ($row = mysqli_fetch_assoc($query_result)) {
echo $row['value'];
}
?>
I have tried substituting $q with '$q' and '".$q."' and none of those print out the case_id that I need. I also tried using the mysqli_stmt_* functions but they printed nothing but blank as well. Our server uses PHP version 5.3.3 if that is helpful.
Thanks again.
Do it like so
<?php
$q = 'mercy_west';
$query = "SELECT col1,col2,col3,col4 FROM database.table WHERE field_name = 'hospital_name' AND value = ?";
if($stmt = $db->query($query)){
$stmt->bind_param("s",$q); // s is for string, i for integer, number of these must match your ? marks in query. Then variable you're binding is the $q, Must match number of ? as well
$stmt->execute();
$stmt->bind_result($col1,$col2,$col3,$col4); // Can initialize these above with $col1 = "", but these bind what you're selecting. If you select 5 times, must have 5 variables, and they go in in order. select id,name, bind_result($id,name)
$stmt->store_result();
while($stmt->fetch()){ // fetch the results
echo $col1;
}
$stmt->close();
}
?>
Yes mysql_real_escape_string() is deprecated.
One solution, as hinted by answers like this one in that post you included a link to, is to use prepared statements. MySQLi and PDO both support binding parameters with prepared statements.
To continue using the mysqli_* functions, use:
mysqli_prepare() to get a prepared statement
mysqli_stmt_bind_param() to bind the parameter (e.g. for the WHERE condition value='$q')
mysqli_stmt_execute() to execute the statement
mysqli_stmt_bind_result() to send the output to a variable.
<?php
$q = 'Hospital_Name';
$query = "SELECT value FROM database.table WHERE field_name = 'hospital_name' AND value = ?";
$statement = mysqli_prepare($conn, $query);
//Bind parameter for $q; substituted for first ? in $query
//first parameter: 's' -> string
mysqli_stmt_bind_param($statement, 's', $q);
//execute the statement
mysqli_stmt_execute($statement);
//bind an output variable
mysqli_stmt_bind_result($stmt, $value);
while ( mysqli_stmt_fetch($stmt)) {
echo $value; //print the value from each returned row
}
If you consider using PDO, look at bindparam(). You will need to determine the parameters for the PDO constructor but then can use it to get prepared statements with the prepare() method.

oci_bind_by_name() returns error

I'm using PHP to query oracle DB and everything works great unless i try to use oci_bind_by_name to replace a variable
$link = oci_connect("user","password","server/service");
$sql = "SELECT name FROM customers WHERE name LIKE '%:name%'";
$query= oci_parse($link, $sql);
$name = "Bruno";
oci_bind_by_name($query, ":name", $name);
$execute = oci_execute($query);
I also tried to escape the quotes like this, but it returns the same error, i assume it's a problem with the wildcards %
$sql = "SELECT name FROM customers WHERE name LIKE \"%:name%\" ";
The error is not specific:
( ! ) Warning: oci_bind_by_name(): in D:\gdrive\www\sites\pulseiras\php\engine.php on line 30
I'd like to use bind by name to avoid sql injection, how can i make it work ?
OCI is inserting the bound variable to your query and ending up with something like this:
SELECT name FROM customers WHERE name LIKE '%'Bruno'%'
Obviously a couple of unnecessary quotes have been added. This happens because a bound variable is treated as a single item.
You need to modify the variable before you bind, so:
$sql = "SELECT name FROM customers WHERE name LIKE :name"; // chars removed.
$query= oci_parse($link, $sql);
$name = "%Bruno%"; // chars added.
oci_bind_by_name($query, ":name", $name);
As usual, the PHP manual has many useful examples.
It's amazing how the brain only seems to start working after posting the question on stackoverflow. It turns out the solution is to isolate the wildcards and concatenating with the variable:
$sql = "SELECT name FROM customers WHERE name LIKE '%' || :name || '%' ";
$name = "Bruno";
oci_bind_by_name($query, ":name", $name);
$execute = oci_execute($query);

Error with mysql statement

I'm trying to blind my MySql query I noob in this, I want prevent to SQL Injection on my query. This is my statement but have one error
$sql = $conn ->prepare("SELECT * FROM Personas WHERE concat(nombre1,' ',apellido1) LIKE '% :name %'");
$sql-> bind_param('name', $q);
Warning: mysqli_stmt::bind_param(): Number of variables doesn't match
number of parameters in prepared statement in
this work fine but that is a bad way
$sql="SELECT * FROM Personas WHERE concat(nombre1,' ',apellido1) LIKE '%".$q."%';
Please help me with this and what other way Can I use to protect my query in my PHP Code
Thank you for all, that was my solution
$sql = $conn ->prepare('SELECT * FROM Personas WHERE concat(nombre1," ",apellido1) LIKE ? ');
$key = "%".$q."%";
$sql-> bind_param('s', $key);
Use bind_param this way:
$sql= $conn->prepare("SELECT * FROM Personas WHERE concat(nombre1,' ',apellido1) LIKE :name");
$q= "%$q%";
$sql->bindParam(':name', $q);
$sql->execute();
The mysql documentation uses question marks (?) to indicate where a subsequent bind_param value should be placed. Try replacing ":name" with the a "?" in the query and your bind_param should follow the syntax bind_param("s", $q) where "s" is a string identifying the types of values being bound: s for string, d for decimal, i for integer, etc.

PDO - passing a field name as a variable

I'm just migrating my code from mysql_query style commands to PDO style and I ran into a problem. THe old code looked like this :
$query_list_menu = "SELECT ".$_GET['section_name']." from myl_menu_hide_show WHERE id='".$_GET['id']."'";
And the updated code looks like below. Apparently it's not working. I store in $_GET['section_name'] a string that represents a field name from the database. But I think there is a problem when I pass it as a variable. Is the below code valid ? Thanks.
$query_list_menu = "SELECT :section_name from myl_menu_hide_show WHERE id=:id";
$result_list_menu = $db->prepare($query_list_menu);
$result_list_menu->bindValue(':section_name', $_GET['section_name'] , PDO::PARAM_STR);
$result_list_menu->bindValue(':id', $_GET['id'] , PDO::PARAM_INT);
$result_list_menu->execute();
If $_GET['section_name'] contains a column name, your query should be:
$query_list_menu = "SELECT " . $_GET['section_name'] . " from myl_menu_hide_show WHERE id=:id";
Giving:
$query_list_menu = "SELECT :section_name from myl_menu_hide_show WHERE id=:id";
$result_list_menu = $db->prepare($query_list_menu);
$result_list_menu->bindValue(':id', $_GET['id'] , PDO::PARAM_INT);
$result_list_menu->execute();
The reason is that you want the actual name of the column to be in the query - you'd changed it to be a parameter, which doesn't really make much sense.
I'll also add that using $_GET['section_name'] directly like this is a massive security risk as it allows for SQL injection. I suggest that you validate the value of $_GET['section_name'] by checking it against a list of columns before building and executing the query.
There is no good and safe way to select just one field from the record based on the user's choice. The most sensible solution would be to select the whole row and then return the only field requested
$sql = "SELECT * from myl_menu_hide_show WHERE id=?";
$stmt = $db->prepare($query_list_menu);
$stmt->execute([$_GET['id']]);
$row = $stmt->fetch();
return $row[$_GET['section_name']] ?? false;

Categories