I am creating a form where a user tick on the checkbox then 1 will be stored in that column on MySQL table. If the user does not tick then 0 will be stored on that field in the database. One checkbox for one column. My HTML code is :
Type ;<label class="checkbox-inline"><input type="checkbox" name="mentor" value="1" >Mentor</label>
<label class="checkbox-inline"><input type="checkbox" name="core" value="1" >Core</label>
and my PHP code is
$name = mysqli_real_escape_string($DBcon, $_POST['name']);
$mentor;
if (isset ($_POST['mentor']) == "1")
{
$mentor = 1;
}
else
{
$mentor = 0;
}
$core;
if (isset ($_POST['core']) == "1")
{
$core =1;
}
else
{
$core =0;
}
$insert = $DBcon->query("INSERT into contributor(name,mentor,core) VALUES('$name','$mentor','$core')");
But I am getting "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '????\"Exif\0\0MM\0*\0\0\0\0\0\0\0\0\0?\0\0\0\0\0\0?\0\0\0\0\0\0\' at line 1"
this error when I press submit button
PHP uses single quotes to mean literals. That is, the $varname won't be interpreted to mean 0, it will mean $varname. Remove the single quotes and it should work.
"INSERT into contributor(name,mentor,core) VALUES($name,$mentor,$core)"
or
'INSERT into contributor(name,mentor,core) VALUES('.$name.','.$mentor.','.$core.')'
If this is for work, please read up on PHP PDO and the security it adds.
# as #War10ck mentioned, you're mixing Procedural-style with object oriented
$name = $DBCon->real_escape_string($_POST['name']);
# You were comparing a boolean (isset) with "1". Since it's a checkbox, you an do this (or $_POST['mentor'] == "1" since that's your value on the form..)
$mentor = isset($_POST['mentor']) ? 1 : 0;
$core = isset($_POST['core']) ? 1 : 0;
# remove single quotes from your $paramaters
$insert = $DBcon->query("INSERT into contributor(name,mentor,core) VALUES($name, $mentor, $core)");
Note you should use PDO prepared statements as others have mentioned
$stmt = $DBcon->prepare("INSERT INTO contributor(name, mentor, core) VALUES(?,?,?)");
$stmt->bind_param('sssd', $name, $mentor, $core);
$insert = $stmt->execute();
You appear to be mixing procedural and object-oriented mysqli_* statements in your code. You should choose one or the other. Change your line here:
mysqli_real_escape_string($DBcon, $_POST['name']);
to this instead:
$DBCon->real_escape_string($_POST['name']);
In addition, you will also want to remove the nested single quotes in your query statement:
$insert = $DBcon->query("INSERT into contributor(name,mentor,core) VALUES($name,$mentor,$core)");
SECURITY IMPLICATIONS:
I cannot go without saying (and without echoing the comments above), that you are leaving yourself open to SQL Injection attacks using this method. To ensure that you are protected, you should consider using the prepared statements offered by both the mysqli_* and PDO_* extensions.
Consider using the following safer alternative instead of the code you used above:
$DBCon = new \PDO('{dsn}', '{user}', '{pass}', [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_EMULATE_PREPARES => FALSE
]);
$mentor = (isset($_POST['mentor']) AND intval($_POST['mentor']) === 1) ? 1 : 0;
$core = (isset($_POST['core']) AND intval($_POST['core']) === 1) ? 1 : 0;
try {
$stmt = $DBCon->prepare("INSERT INTO contributor(name,mentor,core) VALUES (:name,:mentor,:core)");
$stmt->bindParam(':name', $name, PDO::PARAM_STR);
$stmt->bindParam(':mentor', $mentor, PDO::PARAM_INT);
$stmt->bindParam(':core', $core, PDO::PARAM_INT);
$stmt->execute();
/* Cleanup (if you are finished interacting with the database) */
$stmt = NULL;
$DBCon = NULL;
} catch (\PDOException $e) {
/* Handle Error Here */
}
Related
I find ezSQL library very useful but as far as I see there is no implementation of prepared statements in it, am I right? Or is there something I don't know?
I have checked out the help file which I downloaded from http://justinvincent.com/ezsql
For example: I have some queries like
$stmt = $conn->prepare("INSERT INTO gecici_magaza_detay VALUES ($geciciMagazaId,?,?,?,?)");
$stmt->bind_param("iiss",$gunId,$acikMi,$girisSaati,$cikisSaati);
for($j=0; $j<7; $j++) {
$gunId = $j+1;
$acikMi = (empty($acilis[$j]) || empty($kapanis[$j])) ? 0 : 1;
$girisSaati = $acikMi ? $acilis[$j] : null;
$cikisSaati = $acikMi ? $kapanis[$j] : null;
$stmt->execute();
}
where $conn is a mysqli object.
$conn = new mysqli($servername, $username, $password, $dbname);
but I want to get rid of it completely and use only my $db object which is:
$db = new ezSQL_mysqli();
I hope there is a way of using prepared statements with ezSQL, that would make me more comfortable, otherwise I'll have to use both.
I know this is an old question, but there are options for prepared statements from v3.08+.
When you create your connection you simply use $db->prepareOn();. Here's an example using this code
// To get SQL calls to use prepare statements
$db->prepareOn(); // This needs to be called at least once at instance creation
$db->query_prepared('INSERT INTO profile( name, email, phone) VALUES( ?, ?, ? );', [$user, $address, $number]);
$db->query_prepared('SELECT name, email FROM profile WHERE phone = ? OR id != ?', [$number, 5]);
$result = $db->queryResult(); // the last query that has results are stored in `last_result` protected property
foreach ($result as $row) {
echo $row->name.' '.$row->email;
}
More information can be found on the new Wiki
No, there isn't any built-in prepared statement feature in ezsql.
Use $db->escape() function for unsafe variables. This is the safest option available.
This question already has answers here:
Can I parameterize the table name in a prepared statement? [duplicate]
(2 answers)
Closed 5 years ago.
I'm trying to execute delete SQL statement upon button press, which was working if I binded 1 parameter, but I want to make the delete.php generic, as not to have multiple of them just for referencing different tables:
<?php
include "header.php";
include "db.php";
$_POST['table'] = "customer";
$_POST['column'] = "cID";
$_POST['del_id'] = 26;
if(isset($_POST['del_id']))
{
if ($stmt = $conn->prepare("DELETE FROM customer WHERE ? = ?"))
{
$stmt->bind_param('si', $_POST['column'], $_POST['del_id']);
$stmt->execute();
}
else echo("Oops");
}
This binding executes but doesn't do anything to the table, only binding the final value 'del_id', executes correctly, and binding 3 arguments including the table name, just causes prepare() to fail.
I am setting the _POST vars in other places from AJAX POSTs, above is just for testing that this bit works or not. I also haven't gotten round to doing validation yet before that comes up.
Very PHP nooby, likely a simple mistake, or just something I'm not aware of, in which case I'd be rather curious as to why the table/column names can't be parameterised, as it's been eluding me for some time. As a workaround, would some form of concatenation work instead, to be able to drop dynamic names into this query from multiple different places?
You should validate both the table name and column name before running the delete.
Since you can't prepare either the table or column names, just put them in the sql statement before the prepare.
<?php
include "header.php";
include "db.php";
$_POST['table'] = "customer";
$_POST['column'] = "cID";
$_POST['del_id'] = 26;
// Add code to prevent SQL injection
$table = $_POST['table'] == 'customer' ? $_POST['table'] : '';
$column = $_POST['column'] == 'customer' ? $_POST['column'] : '';
if(isset($_POST['del_id']) && $table != '' && $column != '') {
if ($stmt = $conn->prepare("DELETE FROM `".$table."` WHERE `".$column."` = ?"))
{
$stmt->bind_param('i', $_POST['del_id']);
$stmt->execute();
}
else echo("Oops");
}
Yes, to achieve this you will need to have a combination of concatenation and parameters for the Prepared Statement:
if ($stmt = $conn->prepare("DELETE FROM " . $_POST['table'] . " WHERE " . $_POST['column'] . " = ?"))
{
$stmt->bind_param('si', $_POST['del_id']);
$stmt->execute();
}
Make sure you pay attention on additional validations you will need on the table and column names. This should be validated against your data model and not just making sure its a valid identifier. Further, take a look at some ORMs/Query Builders to learn how to elaborate upon this idea. It's a good learning exercise.
I create a simple site for findID when I write the email.
HTML CODE
<form action="test.php" method="post">
<input type="text" name="user_id_test" id="user_id_test">
<br>
<br>
<input type="submit" value="Find ID">
</form>
PHP CODE
<?php
//include database
include 'include/db.inc';
$emailUser = $_POST['user_id_test'];
$findNewID = mysqli_query($connessione,"SELECT user_id FROM user_tmplt WHERE user_mail = $emailUser");
if ($findNewID != "") {
var_dump($findNewID);
echo "$findNewID";
} else {
echo "Errore: " . $findNewID . "<br>" . mysqli_error($connessione) ."<br>";
}
mysqli_error($connessione);
?>
I try to find ID for email: dfaf#dfaf.fa (it is in my database with ID 13) and I've this error You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '#dfaf.fa' at line 1
You should use prepared statements to avoid this kind of errors and to avoid SQL Inyection:
$stmt = mysqli_prepare($connessione,"SELECT user_id FROM user_tmplt WHERE user_mail = ?");
if ( !$stmt ) { someErrorHandlingHere(); }
mysqli_stmt_bind_param($stmt, "s", $emailUser);
// same here: mysqli_stmt_bind_param may fail -> returns false
mysqli_stmt_execute($stmt);
// same here: mysqli_stmt_execute may fail -> returns false
mysqli_stmt_bind_result($stmt, $userId);
// and so on and on: error handling
mysqli_stmt_fetch($stmt);
echo "The user id es: {$userId}";
It is about passing email as integer, pass it as string..
mysqli_query($connessione,"SELECT user_id FROM user_tmplt WHERE user_mail = $emailUser");
to
mysqli_query($connessione,"SELECT user_id FROM user_tmplt WHERE user_mail = '".$emailUser."' ");
This would work but it is not safe to pass parameters within the queries directly, make the sql injection safe first...
Your immediate problem (as has already been answered) is/was that you didn't mark the string parameter (the email-address) as a string literal within the SQL query. The MySQL server therefore interpreted it as an identifier (like a database/table/field name). And since # is an invalid character within an identifier the server reported the error you've posted, see http://dev.mysql.com/doc/refman/5.0/en/identifier-qualifiers.html.
To mark a string literal within a query you put it (by default) in single-quotes:
SELECT x FROM table WHERE y=z // compares the value of the field y with the value of the field z in each record
SELECT x FROM table WHERE y='z' // compares the value of the field y with the string literal 'z' <- that's what you want
Anyway, here's an example (that addresses some other issues) using PDO instead of mysqli_*:
<?php
define('POST_FIELD_MAIL', 'user_id_test');
if ( !isset($_POST[POST_FIELD_MAIL]) ) { // maybe the resource (...script) has been requested without that parameter?
trigger_error('missing parameter '.POST_FIELD_MAIL, E_USER_ERROR);
}
else {
/** that's you part you probably want in inc/db.php */
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'localonly', 'localonly');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // that's why there's not error handling code after each and every call to a pdo function/method
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
/* ***** */
try {
$stmt = $pdo->prepare('SELECT user_id FROM user_tmplt WHERE user_mail=?'); // avoiding sql injections
$stmt->execute( array($_POST[POST_FIELD_MAIL]) );
$row = $stmt->fetch();
if (!$row) {
echo '<div>no such record</div>';
}
else {
echo '<div>user_id=', htmlspecialchars($row['user_id']), '</div>';
}
}
catch(PDOException $pex) {
yourErrorHandler();
}
}
This query is exposed to sql injections. Always sanitize or escape special characters in a string before using in a where clause. In this case wrap $email with quotes.
ie. change
$email to '".$emailUser."'
In the where clause.
I'm trying to insert a PHP function into a foreach loop in order to generate values for each row fetched from the db for the variable $Match.
The db query itself works properly, and the function which assigns values to variable $Match works properly when I test it with hard-coded values, but when I try combining it with the rest of the code in order to use db values it stops working properly. Specifically: 1) It only runs the first IF statement; and 2) If that statement is true, it's adding the same value for every row.
I've uploaded a functional example with hard-coded values to this sandbox http://sandbox.onlinephpfunctions.com/code
Declaring values for test case:
$User_Waist = "26";
$User_Hip = "38";
$Match = Null;
$waistMatch = Null;
$hipMatch = Null;
Query database & fetchAll
$stmt = $conn - > prepare("SELECT * FROM SizeChart WHERE FIND_IN_SET($User_Waist, Waist_Measurement) > 0 OR FIND_IN_SET($User_Hip, Hip_Measurement) > 0;");
$stmt - > bindValue(':Waist_Measurement', $Waist_Measurement, PDO::PARAM_STR);
$stmt - > bindValue(':Hip_Measurement', $Hip_Measurement, PDO::PARAM_STR);
$stmt - > execute();
$rows = $stmt - > fetchAll(PDO::FETCH_ASSOC);
Loop through results
$count = 0;
foreach($rows as $row) {
$count++;
Adds value to variable $Match
if (strpos($row['Waist_Measurement'], $User_Waist) !== false) {
$waistMatch = 'waistFit';
}
if (strpos($Hip_Measurement, $User_Hip) !== false) {
$hipMatch = 'hipFit';
}
$Match = $waistMatch.', '.$hipMatch;
Display Results
echo "Size #: ".$row['Size']."; Fit Matches: ".' '.$Match."; Waist: ".$row['Waist_Measurement'], "; Hip: ".$row['Hip_Measurement'], ".<br />";
The SQL text doesn't contain bind placeholders :Waist_Measurement or :Hip_Measurement.
The bindValue calls aren't going to work, since there's no placeholder of the specified name to bind a value to.
Here's an example that uses a bind placeholder named :fum. Note that this string appears both in the SQL text and as an argument to bindValue or bindParam.
$foo = "bar";
$sql = "SELECT fee FROM fi WHERE fo = :fum ";
// ^^^^
$sth = $dbh->prepare($sql);
$sth->bindValue(":fum", $foo, PDO::PARAM_STR);
// ^^^^
$sth->execute();
FOLLOWUP
This is the SQL text in your prepare.
(I notice that there's a semicolon at the end of the SQL text, and that may be causing an error; I normally don't include a trailing semicolon in my SQL text.)
SELECT *
FROM SizeChart
WHERE FIND_IN_SET($User_Waist, Waist_Measurement) > 0
OR FIND_IN_SET($User_Hip, Hip_Measurement) > 0
But the point is that there aren't any bind placeholders in that SQL text. When you do a:
->bindValue(":Waist_Measurement",...
^^^^^^^^^^^^^^^^^^
That's essentially saying "Hey! There's a string literal ':Waist_Measurement' in the SQL text of the prepared statement", and saying "in place of that string literal, use this value...".
But the thing is, that string literal does not appear in your SQL text. There's no bind placeholder in the statement. (There's not even a placeholder of a different name, I don't see any colon characters anywhere in the SQL.)
I'm surprised that PDO isn't throwing an error. Actually, PDO probably is throwing an error, but your code is ignoring it. If your code isn't going to check the return from prepare, execute, et al. then you can have PDO do the check and throw the exception for you, by specifying an attribute on the connection.
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Also...
The inclusion of PHP variables $User_Waist and $User_Hip is a little unusual in a prepared statement. One of the benefits of prepared statements is that variables representing values can be replaced with bind placeholders.
(I'm confused by what you are trying to do, I can't tell you how to fix it.)
In a mysqli prepared statement, a NULL gets turned into '' (in the case of a string) or 0 (in the case of an integer). I would like to store it as a true NULL. Is there any way of doing this?
It's possible to bind a true NULL value to the prepared statements (read this).
You can, in fact, use mysqli_bind_parameter to pass a NULL value to the database. simply create a variable and store the NULL value (see the manpage for it) to the variable and bind that. Works great for me anyway.
Thus it'll have to be something like:
<?php
$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'world');
// person is some object you have defined earlier
$name = $person->name();
$age = $person->age();
$nickname = ($person->nickname() != '') ? $person->nickname() : NULL;
// prepare the statement
$stmt = $mysqli->prepare("INSERT INTO Name, Age, Nickname VALUES (?, ?, ?)");
$stmt->bind_param('sis', $name, $age, $nickname);
?>
This should insert a NULL value into the database.
For anyone coming looking at this because they are having problems binding NULL in their WHERE statement, the solution is this:
There is a mysql NULL safe operator that must be used:
<=>
Example:
<?php
$price = NULL; // NOTE: no quotes - using php NULL
$stmt = $mysqli->prepare("SELECT id FROM product WHERE price <=> ?"); // Will select products where the price is null
$stmt->bind_param($price);
?>
The comments to the PHP documentation on mysqli_stmt::bind_param indicate that passing in NULL was not easily possible.
Please see #creatio's answer: https://stackoverflow.com/a/6892491/18771
Solutions offered in the comments do some pre-preparation work on the prepared statement, replacing the "?" markers with "NULL" for every param that has the PHP null value. The modified query string is then used.
The following function is from user comment 80119:
function preparse_prepared($sQuery, &$saParams)
{
$nPos = 0;
$sRetval = $sQuery;
foreach ($saParams as $x_Key => $Param)
{
//if we find no more ?'s we're done then
if (($nPos = strpos($sQuery, '?', $nPos + 1)) === false)
{
break;
}
//this test must be done second, because we need to
//increment offsets of $nPos for each ?.
//we have no need to parse anything that isn't NULL.
if (!is_null($Param))
{
continue;
}
//null value, replace this ? with NULL.
$sRetval = substr_replace($sRetval, 'NULL', $nPos, 1);
//unset this element now
unset($saParams[$x_Key]);
}
return $sRetval;
}
(It's not really the coding style I would have done it in, but if it works...)
I store all parameters in an array and pass them in bind_param function using array_shift($myArray). NULL is accepted like that.
<?php
$mysqli=new mysqli('localhost','root','','test');
$mysqli->query("CREATE TABLE test_NULL (id int(11))");
if($query=$mysqli->prepare("insert into test_NULL VALUES(?)")){
$query->bind_param('i',$null); //note that $null is undefined
$query->execute();
}else{
echo __LINE__.' '.$mysqli->error;
}
?>