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.
Related
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 */
}
Im new to database and i have written a LOT of PHP code that accesses a database using MySQL.
I didnt take into account SQL injection attacks so i have to re-write all that PHP code to use mysql prepared statements.
After looking at videos on how to used prepared SQL statements, to perform just ONE SQL command requires a whole lot of "prepared" statements. My existing code has lots of different SQL statements all over the place, it would be a nightmare to change all that code to pack and unpack all the required preparation for each "prepared" statement command.
Is there some kind of wrapper i can use to prevent turning one line of regular SQL into 6 or 7 lines of prepared statements?
For example use to do this line line of SQL
SELECT * from users where userid=10
needs many more lines of prepared SQL statements, especially if there are lots of other SQL statements too it now becomes very complex.
Is there was some sort of one line wrapper that i can call that accepts the template SQL string, plus the parameters, which also executes the command and returns the result in just one line of wrapper for different types of MYSQL statements it would be great and the code would be much less confusing looking and error prone.
For example
$users=WrapAndExecute($db,"SELECT * from users where userid=?","s",$userid);
$data=WrapAndExecute($db,"UPDATE table SET username=?,city=?","ss",$name,$city);
$result=WrapAndExecute($db,"DELETE from table where id=?","s",$userid);
$result=WrapAndExecute($db,"INSERT into ? (name,address) VALUES(?,?)","ss","users",$name,$address);
Each of those lines above would create a prepared statement template, do the bind, execute it and return the result that a regular MYSQL statement would. This would create minimal impact on existing code.
Anybody knows how to do this or if some easy php library or class already exists to do this, that i can just import and start using it?
Thanks
You don't need to change a query to a prepared statement if it has no PHP variables in it. If it has just constant expressions, it's safe from SQL injection.
$sql = "SELECT * from users where userid=10"; // Safe!
$stmt = $pdo->query($sql);
$data = $stmt->fetchAll();
You don't need to change a query that contains PHP variables, as long as the value of that variable is a constant specified in your code. If it doesn't take its value from any external source, it's safe.
$uid = 10;
$sql = "SELECT * from users where userid=$uid"; // Safe!
$stmt = $pdo->query($sql);
$data = $stmt->fetchAll();
You don't need to change a query that contains PHP variables, as long as you can filter the value to guarantee that it won't risk an SQL injection. A quick and easy way to do this is to cast it to an integer (if it's supposed to be an integer).
$uid = (int) $_GET['uid'];
$sql = "SELECT * from users where userid=$uid"; // Safe!
$stmt = $pdo->query($sql);
$data = $stmt->fetchAll();
That leaves cases where you are using "untrusted" values, which may have originated from user input, or reading a file, or even reading from the database. In those cases, parameters are the most reliable way to protect yourself. It's pretty easy:
$sql = "SELECT * from users where userid=?"; // Safe!
// two lines instead of the one line query()
$stmt = $pdo->prepare($sql);
$stmt->execute([$_GET['uid']]);
$data = $stmt->fetchAll();
In a subset of cases, you need one additional line of code than you would normally use.
So quit your whining! ;-)
Re your comment about doing prepared statements in mysqli.
The way they bind variables is harder to use than PDO. I don't like the examples given in http://php.net/manual/en/mysqli.prepare.php
Here's an easier way with mysqli:
$sql = "SELECT * from users where userid=?"; // Safe!
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('i', $_GET['uid']);
$stmt->execute();
$result = $stmt->get_result();
$data = $result->fetch_all();
I don't like the stuff they do in their examples with bind_result(), that's confusing and unnecessary. Just use get_result(). So with mysqli, you need two more lines of code than you would with PDO.
I've written query wrappers for mysqli that emulate the convenience of PDO's execute() function. It's a PITA to get an array mapped to the variable-arguments style of bind_param().
See the solution in my answers to https://stackoverflow.com/a/15933696/20860 or https://stackoverflow.com/a/7383439/20860
I were in the same boat, and I wrote such a wrapper that works exactly the way you want, save for it's being a class, not a function.
$user = $sdb->getRow("SELECT * from users where userid=?s", $userid);
$sdb->query("UPDATE table SET username=?s, city=?s", $name, $city);
$sdb->query("DELETE from table where id=?s", $userid);
$sdb->query("INSERT into ?n (name,address) VALUES(?s,?s)","users", $name, $address);
The above is a working code, as long as you have somewhere in your bootstrap file
$db = mysqli_connect(...);
...
require 'safemysql.class.php';
$sdb = new SafeMySQL('mysqli' => $db);
Note that none of the other suggestions could do anything like that.
Also note that if I were writing it today, I would have used PDO, as this class is duplicating a lot of functionality already exists in PDO.
Take a look at the PDO extension in PHP - http://php.net/manual/en/intro.pdo.php: it it secure against injections thanks to prepared statements; also, it allows you to connect to many different databases (e.g. MySQL, MSSQL, etc.).
You can then build your own wrapper as you wish to keep it clean; for example your own wrapper could be as follows:
(following example will return user rows as objects)
// connect to DB
$GLOBALS['default_db'] = new DB('localhost','db_name','username','password') ;
// Get users and output results
$query = new DBQuery('SELECT * FROM users WHERE userid = ?',array(10)) ;
var_dump($query -> results()) ;
var_dump($query -> num_rows()) ;
// DB connection
class DB {
public $connection;
public function __construct($host , $dbname , $username , $password) {
$this->connection = new \PDO('mysql:host=' . $host . ';dbname=' . $dbname , $username , $password);
}
}
// Wrapper
class DBQuery {
private $num_rows = 0;
private $results = array();
public function __construct($query , $params = null , $class_name = null , DB $db = null) {
if ( is_null($db) ) {
$db = $GLOBALS['default_db'];
}
$statement = $db->connection->prepare($query);
$statement->execute($params);
$errors = $statement->errorInfo();
if ( $errors[2] ) {
throw new \Exception($errors[2]);
}
$fetch_style = ($class_name ? \PDO::FETCH_CLASS : \PDO::FETCH_OBJ);
$this->results = $class_name ? $statement->fetchAll($fetch_style , $class_name) : $statement->fetchAll($fetch_style);
$this->num_rows += $statement->rowCount();
while ( $statement->nextrowset() ) {
$this->results = array_merge($this->results,$class_name ? $statement->fetchAll($fetch_style , $class_name) : $statement->fetchAll($fetch_style));
$this->num_rows += $statement->rowCount();
}
}
public function num_rows() {
return $this->num_rows;
}
public function results() {
return $this->results;
}
}
Since a key requirement seems to be that you can implement this with minimal impact on your current codebase, it would have been helpful if you had told us what interface you currently use for running your queries.
While you could use PDO:
that means an awful lot of work if you are not already using PDO
PDO exceptions are horrible
Assuming you are using procedural mysqli (and have a good reason not to use mysqli_prepare()) its not that hard to write something (not tested!):
function wrapAndExecute()
{
$args=func_get_args();
$db=array_shift($args);
$stmt=array_shift($args);
$stmt_parts=explode('?', $stmt);
if (count($args)+1!=count($stmt_parts)) {
trigger_error("Argument count does not match placeholder count");
return false;
}
$real_statement=array_shift($stmt_parts);
foreach ($args as $k=>$val) {
if (isnull($val)) {
$val='NULL';
} else if (!is_numeric($val)) {
$val="'" . mysqli_real_escape_string($db, $val) . "'";
}
$real_statement.=$val . array_shift($stmt_parts);
}
return mysqli_query($db, $real_statement);
}
Note that this does not handle IS [NOT] NULL nicely nor a literal '?' in the statement nor booleans (but these are trivial to fix).
Procedure
CREATE PROCEDURE prSample1()
BEGIN
SELECT Name
FROM StudentsList;
END;
PHP Code
$objMain = new Main();
$objMain->getStudentsName();
class Main
{
function __construct()
{
$Conn = new mysqli('localhost', 'root', '', 'sampleDB');
}
function getStudentsName()
{
$strSQL = "CALL prSample1()";
$stmt = $Conn->prepare($strSQL);
$stmt->execute();
$stmt->bind_result($Name);
while($stmt->fetch())
$arrNames = array('Name'=>$Name);
}
I don't get any error or any warning.
I would like to Know the effect of the Following statements on the php code after getting the values in array that is before the last brace ends.
1.$stmt->close()
2.$stmt->reset()
Also let me know where to use the following statements and how to use them
1.$stmt->free_result()
2.$stmt->store_result()
3.$stmt->bind_result()
Please correct me if I have did any mistakes in coding standards and proper way to use prepared statements
I have many functions like
updateUser($id,$username,$email)
updateMusic($id, $music)
etc...
Is there a generic function to avoid SQL injections ?
I just want to avoid using mysql_real_escape_string for each parameter I have
$username = mysql_real_escape_string($username);
$email= mysql_real_escape_string($email);
$music= mysql_real_escape_string($music);
ALWAYS use prepared statements
Do NOT use mysql driver, use mysqli or PDO
You should use parameterization and let the database driver handle it for you, i.e. with PDO:
$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', $user, $password);
$stmt = $dbh->prepare('INSERT INTO REGISTRY (name, value) VALUES (:name, :value)');
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);
// insert one row
$name = 'one';
$value = 1;
$stmt->execute();
Code from Bobby-Tables.
you may use,
list($id,$music) = array_map('mysql_real_escape_string',array($id,$music))
but prepared statements rocks
No there isn't, but you can parse all your inputs ( eg. GET and POST ) at beggining of the script
I'm playing around with MySQLi at the moment, trying to figure out how it all works. In my current projects I always like to echo out a query string while coding, just to make sure that everything is correct, and to quickly debug my code. But... how can I do this with a prepared MySQLi statement?
Example:
$id = 1;
$baz = 'something';
if ($stmt = $mysqli->prepare("SELECT foo FROM bar WHERE id=? AND baz=?")) {
$stmt->bind_param('is',$id,$baz);
// how to preview this prepared query before acutally executing it?
// $stmt->execute();
}
I've been going through this list (http://www.php.net/mysqli) but without any luck.
EDIT
Well, if it's not possible from within MySQLi, maybe I'll stick with something like this:
function preparedQuery($sql,$params) {
for ($i=0; $i<count($params); $i++) {
$sql = preg_replace('/\?/',$params[$i],$sql,1);
}
return $sql;
}
$id = 1;
$baz = 'something';
$sql = "SELECT foo FROM bar WHERE id=? AND baz=?";
echo preparedQuery($sql,array($id,$baz));
// outputs: SELECT foo FROM bar WHERE id=1 AND baz=something
Far from perfect obviously, since it's still pretty redundant — something I wanted to prevent — and it also doesn't give me an idea as to what's being done with the data by MySQLi. But I guess this way I can quickly see if all the data is present and in the right place, and it'll save me some time compared to fitting in the variables manually into the query — that can be a pain with many vars.
I don't think you can - at least not in the way that you were hoping for. You would either have to build the query string yourself and execute it (ie without using a statement), or seek out or create a wrapper that supports that functionality. The one I use is Zend_Db, and this is how I would do it:
$id = 5;
$baz = 'shazam';
$select = $db->select()->from('bar','foo')
->where('id = ?', $id)
->where('baz = ?', $baz); // Zend_Db_Select will properly quote stuff for you
print_r($select->__toString()); // prints SELECT `bar`.`foo` FROM `bar` WHERE (id = 5) AND (baz = 'shazam')
I have struggled with this one in the past. So to get round it I wrote a little function to build the SQL for me based on the SQL, flags and variables.
//////////// Test Data //////////////
$_GET['filmID'] = 232;
$_GET['filmName'] = "Titanic";
$_GET['filmPrice'] = 10.99;
//////////// Helper Function //////////////
function debug_bind_param(){
$numargs = func_num_args();
$numVars = $numargs - 2;
$arg2 = func_get_arg(1);
$flagsAr = str_split($arg2);
$showAr = array();
for($i=0;$i<$numargs;$i++){
switch($flagsAr[$i]){
case 's' : $showAr[] = "'".func_get_arg($i+2)."'";
break;
case 'i' : $showAr[] = func_get_arg($i+2);
break;
case 'd' : $showAr[] = func_get_arg($i+2);
break;
case 'b' : $showAr[] = "'".func_get_arg($i+2)."'";
break;
}
}
$query = func_get_arg(0);
$querysAr = str_split($query);
$lengthQuery = count($querysAr);
$j = 0;
$display = "";
for($i=0;$i<$lengthQuery;$i++){
if($querysAr[$i] === '?'){
$display .= $showAr[$j];
$j++;
}else{
$display .= $querysAr[$i];
}
}
if($j != $numVars){
$display = "Mismatch on Variables to Placeholders (?)";
}
return $display;
}
//////////// Test and echo return //////////////
echo debug_bind_param("SELECT filmName FROM movies WHERE filmID = ? AND filmName = ? AND price = ?", "isd", $_GET['filmID'], $_GET['filmName'], $_GET['filmPrice']);
I have also build a little online tool to help.
Mysqli Prepare Statement Checker
I recently updated this project to include composer integration, unit testing and to better handle accepting arguments by reference (this requires updating to php 5.6).
In response to a request I received on a project I created to address this same issue using PDO, I created an extension to mysqli on github that seems like it addresses your issue:
https://github.com/noahheck/E_mysqli
This is a set of classes that extend the native mysqli and mysqli_stmt classes to allow you to view an example of the query to be executed on the db server by interpolating the bound parameters into the prepared query then giving you access to resultant query string as a new property on the stmt object:
$mysqli = new E_mysqli($dbHost, $dbUser, $dbPass, $dbName);
$query = "UPDATE registration SET name = ?, email = ? WHERE entryId = ?";
$stmt = $mysqli->prepare($query);
$stmt->bindParam("ssi", $_POST['name'], $_POST['email'], $_POST['entryId']);
$stmt->execute();
echo $stmt->fullQuery;
Will result in:
UPDATE registration SET name = 'Sue O\'reilly', email = 'sue.o#example.com' WHERE entryId = 5569
Note that the values in the fullQuery are escaped appropriately taking into account the character set on the db server, which should make this functionality suitable for e.g. log files, backups, etc.
There are a few caveats to using this, outlined in the ReadMe on the github project, but, especially for development, learning and testing, this should provide some helpful functionality.
As I've outlined in the github project, I don't have any practical experience using the mysqli extension, and this project was created at the request of users of it's sister project, so any feedback that can be provided from devs using this in production would be greatly appreciated.
Disclaimer - As I said, I made this extension.
Just set it to die and output the last executed query. The Error handling should give you meaningful information which you can use to fix up your query.
You can turn on log queries on mysql server.
Just execute command:
sql> SHOW VARIABLES LIKE "general_log%";
sql> SET GLOBAL general_log = 'ON';
And watch queries in the log file.
After testing turn log off:
sql> SET GLOBAL general_log = 'OFF';
I was able to use var_dump() to at least get a little more info on the mysqli_stmt:
$postmeta_sql = "INSERT INTO $db_new.wp_postmeta (post_id, meta_key, meta_value) VALUES (?, ?, ?)";
$stmt = $new_conn->prepare($postmeta_sql);
$stmt->bind_param("sss", $post_id, $meta_key, $meta_value);
echo var_dump($stmt);
$stmt->execute();
$stmt->close();