Using prepared statements but quotes not being escaped or removed - php

I am having an issue getting some things to insert into my database. If I put quotes single or double into my text fields it will break the query and will not escape them. I just got done reading that using prepared statements eliminates the need to call mysql_real_escape_string. Can someone tell me if I am executing my query wrong. $companyInfo is an array that contains about 8 rows to be inserted.
function InsertCompanyInfo($companyInfo, $conn) {
foreach($companyInfo as $key => $table) {
$keys = array_keys($table);
$values = null;
$x = 1;
foreach($table as $row => $value) {
$values .= "'$value'";
if($x < count($keys)) {
$values .= ', ';
}
$x++;
}
$sql = $conn->prepare("INSERT INTO {$key} (`" . implode('`, `', $keys) . "`) VALUES ({$values});");
$sql->execute();
$CompanyID = $conn->lastInsertId('CompanyID');
}
return $CompanyID;
}
This is the error I get when I insert qoutes:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax
error or access violation: 1064 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 '1',
''''"'"''"';;''';';')' at line 1' in /var/www/Survey/InsertFunctions.php:20 Stack trace: #0
/var/www/Survey/InsertFunctions.php(20): PDOStatement->execute() #1
/var/www/Survey/testProcess.php(8): InsertCompanyInfo(Array, Object(PDO)) #2 {main} thrown
in /var/www/Survey/InsertFunctions.php on line 20

Prepared statements work by separating the query structure and the values in code like so:
$stmt = $pdo->prepare('INSERT INTO foo (bar) VALUES (?)');
This is the query structure, which the database is given first to understand. Then you give it the values separately:
$stmt->execute(array('baz'));
What you're doing instead is you call prepare on a completely formed query which includes crudely interpolated values. There's nothing prepare can do here. The entire problem of escaping values is that the database cannot figure out what a value was and what your part of the query was after the fact. If you're giving the query fully formed and incorrectly escaped to the database, it can't magically recognise what was supposed to be what. You need to add placeholders to the query and provide the corresponding values in a separate step.

Related

Mistake in SQL syntax.. (bindValue?)

I am trying to create an update query and I am looping in some set stuff to a var called $str and I cant seem to get it to work.
if (is_numeric($id)) {
if (!empty($values) && !empty($table_name)) {
$str = '';
$sql = "UPDATE `$table_name` SET :update_values WHERE `$column_name` = :id";
// Its one because we dont use ID like that
$i = 1;
foreach ($values as $key => $value) {
if ($key != $column_name) {
// Exclude the last one from having a comma at the end
if ($i == count($values) - 1) {
$str .= "$key='" . $value . "'";
} else {
$str .= "$key='" . $value . "', ";
$i++;
}
}
}
$query = $this->dbh->prepare($sql);
$query->bindValue('update_values', $str, PDO::PARAM_STR);
$query->bindValue(':id', $id, PDO::PARAM_INT);
$query->execute();
return true;
} else {
return false;
}
} else{
return false;
}
}
Output:
Fatal error: Uncaught PDOException: SQLSTATE[42000]: Syntax error or
access violation: 1064 You have an error in your SQL syntax; check the
manual that corresponds to your MariaDB server version for the right
syntax to use near ''note_name=\'yeet\', note_date=\'2020-02-20\',
note_desc=\'asdasdasdasdadsasdads' at line 1
Am I making any obvious mistakes?
Also for the life of me I don't know what the backslashes in front of the values mean.
In MySQL, identifiers cannot be provided as values.
References to columns must appear in the text of the SQL statement, they cannot be provided through bind parameters. This holds true for table names, column names, function names.
There is no workaround; this is a by-design restriction. There's several reasons for this. One of the most straightforward reasons is understanding how a SQL statement gets prepared, the information that is needed to come up with an execution plan, the tables and columns have to be known at prepare time (for the semantic check and privilege check. The actual values can be deferred to execution time.
Bind placeholders are for providing values, not identifiers.
With the code given, what MySQL is seeing something along the lines of
UPDATE `mytable` SET 'a string value' WHERE `id_col` = 42
And MySQL is balking at the 'a string value'.
We can (and should) use bind parameters for values.
We could dynamically generate SQL text that looks like this:
UPDATE `mytable`
SET `col_one` = :val1
, `col_two` = :val2
WHERE `id_col` = :id
and after the SQL text is prepared into statement, we can bind values:
$sth->bindValue(':val1', $value_one , PDO::PARAM_STR );
$sth->bindValue(':val2', $value_two , PDO::PARAM_STR );
$sth->bindValue(':id' , $id , PDO::PARAM_INT );
and then execute

Mapping PHP associative arrays into PDO prepared statements

I'm doing some cleanup and transformation on data (that part is done, whew), and need to insert it into a MySQL table. Having done this kind of thing in Perl previously, I assumed that, as part of processing, it would make sense for me to structure the data as an associative array with the keys being the same as the field names I need to load them into - that way, it would be easy to construct a prepared statement simply by looping over the keys and producing a list of both the named placeholders and the matching values.
However, I can't seem to make this work in PHP/PDO. Test code:
$x = <<<EOD
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
EOD;
$fields = array('name', 'job', 'wallet_size', 'inseam', 'pet_name');
foreach(explode("\n", $x) as $line){
$data = array_combine($fields, explode(' ', $line));
# print_r($data);
$stmt = $dbh->prepare('INSERT INTO foobar VALUES('.':'.implode(', :', $fields));
foreach($fields as $field){
$stmt->bindParam(':'.$field, $data[$field]);
}
$stmt->execute();
}
Frankly, it feels too... graceless and hacky to work - and it doesn't.
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 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 '' at line 1' in tst.php:24
There is a correct way to do this, right? I'd appreciate it if someone would introduce me to the appropriate PHP-flavored phrasing for it.
It's hard to debug SQL when you're staring at the PHP code that formats SQL, instead of the final SQL string itself. I suggest you always create a string variable so you can output it during debugging.
$sql = 'INSERT INTO foobar VALUES('.':'.implode(', :', $fields);
echo "$sql\n";
$stmt = $dbh->prepare($sql);
Outputs:
INSERT INTO foobar VALUES(:name, :job, :wallet_size, :inseam, :pet_name
Now it's very easy to see that you forgot the closing ) at the end of that INSERT statement!
Also, your use of PDO is more difficult than it needs to be. You don't need to use named parameters. You don't need to use bindParam(). Here's how I would write this code:
$fields = array('name', 'job', 'wallet_size', 'inseam', 'pet_name');
$columns = implode(',', $fields);
$placeholders = implode(',', array_fill(1, count($fields), '?'));
$sql = "INSERT INTO foobar ($columns) VALUES ($placeholders)";
echo "$sql\n"; // use this during debugging
$stmt = $dbh->prepare($sql);
foreach(explode("\n", $x) as $line){
$param_values = explode(' ', $line);
$stmt->execute($param_values);
}
Tips:
Prepare the query once, and re-use the prepared statement for each row of data you want to insert.
Pass an array of data values as an argument to execute(). This is easier than using bindParam().
Use positional parameter placeholders (?) instead of named parameter placeholders when your data is in a simple array instead of an associative array.

Error in PDO Update Function

$table="menu_permission";
$field = array('permission'=>$mnuprmis);
$ob->update($table,$field,'staff_id',$stfid);
public function update($table, $fields, $wherefield, $wherefieldvalues)
{
$sql = "update $table set";
foreach ( $fields as $fieldname => $sfieldvalue )
$sql .= $fieldname."= '".$sfieldvalue."',";
$sql = substr($fldquery,0,strlen($fldquery)-1);
$sql .=" where $wherefield = '$wherefieldvalues'";
$q = $this->conn->prepare($sql);
$q->execute();
return true;
}
The error
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]:
Syntax error or access violation: 1064 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 'where staff_id = '1'' at line 1'
in G:\xampp\htdocs\live\Billing Suryas\model\DBConfig.php:171
Stack trace: #0 G:\xampp\htdocs\live\Billing Suryas\model\DBConfig.php(171): PDOStatement->execute()
#1 G:\xampp\htdocs\live\Billing Suryas\pages\permission_pages.php(257): Connection->update('menu_permission', Array, 'staff_id', '1')
#2 {main} thrown in G:\xampp\htdocs\live\Billing Suryas\model\DBConfig.php on line 171
There is no such freaking thing as an $fldquery
$sql = substr($fldquery,0,strlen($fldquery)-1);
^^^ ^^^
Hence your query is only
$sql .=" where $wherefield = '$wherefieldvalues'";
Which results in
where staff_id = '1' // This is your COMPLETE query
That is just one of the problems and it will be fixed when you fix the typo and put in correct variable name there. However a bigger problem will be evident if you read this
How can I prevent SQL injection in PHP?
It might have had to do with the fact that you put single quotes around numeric values, which isn't necessary and might break your query since your DB might regard it as a string instead of a number.
$table="menu_permission";
$field = array('permission'=>$mnuprmis);
$ob->update($table,$field,'staff_id',$stfid);
public function update($table, $fields, $wherefield, $wherefieldvalues)
{
//
// COMPILE QUERY
$sql = "update $table set ";
$col_values_array = array();
foreach ( $fields as $fieldname => $sfieldvalue ) {
$value = is_numeric($sfieldvalue) ? $sfieldvalue : "'$sfieldvalue'";
$col_values_array[] = "$fieldname = $value";
}
$sql .= implode("," , $col_values_array);
$sql .= " where $wherefield = '$wherefieldvalues'";
//
// EXECUTE QUERY
//$q = $this->conn->prepare($sql); --> not required when not using parametrised queries
//$q->execute(); --> not required when not using parametrised queries
$this->conn->query($sql);
return true;
}
Also consider using prepared statements to be safe against SQL injection.

Strip Out All Unwanted Characters

I am using the following code to strip out unwanted characters but it is not stripping out everything and throwing a MySQL error:
$commentmessage = strip_tags($commentmessage);
$commentmessage = htmlentities($commentmessage, ENT_QUOTES);
What code would I use to strip out anything that might cause a MySQL error?
The message I am receiving is:
Error message: SQLSTATE[42000]: Syntax error or access violation: 1064 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 'omg thats the one". One of the logo's we really liked was 1049859 where the f' at line 2**
Evidently you're building your query like so:
$query = "INSERT INTO foo VALUES ('$bar')";
which is breaking because the text of $bar contains single quotes. '
No. *hits you with a rolled-up newspaper* Bad developer.
I could just throw you a string escaping function, or I could show you to do it right like:
$bar = "I am a problematic string!'; DROP TABLE USERS -- "
$query = "INSERT INTO foo VALUES (?)";
$stmt = $dbh->prepare($query);
$stmt->execute(array($bar));
Or:
$bar = "I am a problematic string!'; DROP TABLE USERS -- "
$query = "INSERT INTO foo VALUES (:bar)";
$stmt = $dbh->prepare($query);
$stmt->execute(array('bar'=>$bar));
When you prepare a query like this PHP/PDO/MySQL get together and pre-agree on what types your placeholders are. So your strings are treated like strings without the need for escaping characters. This both prevents rogue single quotes from breaking your query, and help protect you from SQL injection attacks.
You can also re-use prepared statements to increase performance: [relative to un-prepared statements since the SQL only needs to be parsed once, rather than once per query]
$query = "INSERT INTO foo VALUES (?)";
$stmt = $dbh->prepare($query);
foreach( $bars as $bar ) {
$stmt->execute(array($bar));
}

unexpected error on inserting values and error with implode()

I am inserting the values using PDO but i am getting error as:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 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 'desc,price,nick_name,gender,size,color,birth_date,uname,uphone,ucountry,ustate,u' at line 1' in C:\wamp\www\aa\abc.php:58 Stack trace: #0 C:\wamp\www\www\aa\abc.phpphp(58): PDOStatement->execute(Array) #1 {main} thrown in C:\wamp\www\www\aa\abc.php.php on line 58
also getting Warning: implode() [function.implode]: Bad arguments for implode function
Code:
foreach ($_POST['pcheck'] as $p_check) ////storing checkbox values
{
$pcheckp[] = $p_check;
} $finalcheck = implode(',', $pcheck);
foreach ($_POST['pinc'] as $p_inc) ////storing inputfield values
{
$pinc[] = $p_inc;
} $finalpinc = implode(',', $pinc);
$sql = "INSERT INTO list (u_id,list_type,list_ff,breed,title,desc,price,nick_name,gender,size,color,birth_date,uname,uphone,ucountry,ustate,ucity,usite,pcheck,pinc,photo)
VALUES(:uid,:list_type,:list_ff,:breed,:title,:desc,:price,:nick_name,:gender,:size,:color,:date,:uname,:uphone,:ucountry,:ustate,:ucity,:usite,:pcheck,:pinc,:p_photo)";
$q = $db->prepare($sql);
$q->execute(array(':uid'=>dd,
':list_type'=>$list_type,
':breed'=>$breed,
':title'=>$title,
':desc'=>$desc,
':price'=>$price,
':list_ff'=>$list_ff,
':nick_name'=>$nick_name,
':gender'=>$gender,
':size'=>$size,
':color'=>$color,
':date'=>$date,
':uname'=>$uname,
':uphone'=>$uphone,
':ucountry'=>$ucountry,
':ustate'=>$ustate,
':ucity'=>$ucity,
':usite'=>$usite,
':pcheck'=>$finalcheck,
':pinc'=>$finalpinc,
':p_photo'=>$p_photo));
$_POST['pcheck'] and $_POST['pinc'] is used to get checkbox and input values which i am going to store in column in mysql.
I have checked many times to find the syntax error in insert query but nothing wrong is in it
Hoping to get help
Thanks!
for Warning: implode()
$finalcheck = implode(',', $pcheck);
should be
$finalcheck = implode(',', $pcheckp);
also desc is reserved for mysql you need to use it with `
$sql = "INSERT INTO list (`u_id`,`list_type`,`list_ff`,`breed`,`title`,`desc`,`price`,`nick_name`,`gender`,`size`,`color`,`birth_date`,`uname`,`uphone`,`ucountry`,`ustate`,`ucity`,`usite`,`pcheck`,`pinc`,`photo`)
VALUES(:uid,:list_type,:list_ff,:breed,:title,:desc,:price,:nick_name,:gender,:size,:color,:date,:uname,:uphone,:ucountry,:ustate,:ucity,:usite,:pcheck,:pinc,:p_photo)";

Categories