just a quick question about binding in php
I know if you do something like
$select = update my_table set name ='".$posted_name.'" where id=1;
and that is subjected to sql injection
but how will you bind the query below
$select = update my_table set name ='".$posted_name[$a].'" where id=1;
IN my bind array this is how I am binding anything without [$a]
for any example with the first statement I am doing
$select = update my_table set name =:p_update_name where id=1;
$bind_update = array('p_update_name' => $t_update_name);
Try like this:
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value);
// insert one row
$name = 'one';
$value = 1;
$stmt->execute();
you don't have to make all the names equal.
$select = "update my_table set name =:whatever where id=1";
$bind_update = array('whatever' => $random_variable);
will do. so it can be any variable you can think of. As long as it's scalar variable though
Related
I've created an UPDATE statement that updates only if the string's length is greater than 0.
I'm trying to escape quotes within my UPDATE statement once the condition is met. I've been using addslashes($name), but with this new condition addslashes no longer works.
Previous:
$mysqli->query("UPDATE table SET name='".addslashes($name)."' WHERE id=1") or die($mysqli->error);
Current:
$mysqli->query("UPDATE table SET name=IF(LENGTH($name)=0, name, '$name') WHERE id=1") or die($mysqli->error);
Where do I place addslashes() for this function to correctly escape characters? Will this function even work within this particular MySQL statement for PHP?
The problem with your second query is that $name inside the call to LENGTH needs to be in quotes too i.e.
$mysqli->query("UPDATE table SET name=IF(LENGTH('$name')=0, name, '$name') WHERE id=1") or die($mysqli->error);
To use addslashes in that query, you would write:
$mysqli->query("UPDATE table SET name=IF(LENGTH('".addslashes($name)."')=0, name, '".addslashes($name)."') WHERE id=1") or die($mysqli->error);
But really you should consider using a prepared statement instead; then you won't have to worry about escaping quotes. Additionally, you should check the length of $name in PHP and not run the query at all if it is empty. Something like this should work (I'm assuming you have a variable called $id which stores the id value for the update).
if (strlen($name)) {
$stmt = $mysqli->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->bind_param('si', $name, $id);
$stmt->execute() or die($stmt->error);
}
If you have multiple pieces of data to update, you could try something like this:
$name = 'fred';
$city = '';
$state = 'SA';
$id = 4;
$params = array();
foreach (array('name','city','state') as $param) {
if (strlen($$param)) $params[$param] = $$param;
}
$sql = "UPDATE table SET " . implode(' = ?, ', array_keys($params)) . " = ? WHERE id = ?";
$types = str_repeat('s', count($params)) . 'i';
$params['id'] = $id;
$stmt = $mysqli->prepare($sql);
$stmt->bind_param($types, ...$params);
$stmt->execute() or die($stmt->error);
I've got a simple query that is not so easy to execute in PHP script:
SELECT `title` from `MY_TABLE` WHERE id in (30,32,33,44)
Usually I execute sql queries with prepared statements. I place a bunch of ? and than bind parameters. This time the numbers in parenthesis are an array of data I get from the user.
I tried this, but it does not work:
$ids = [30,32,33,44];
$stmt = $mysqli->prepare("
SELECT `title` from `MY_TABLE` WHERE id in (?)
");
// $stmt->bind_param();
$stmt->bind_param("i",$ids);
$stmt->execute();
$stmt->bind_result($title);
$stmt->store_result();
//fetch
How can I execute a set operation with prepared statements?
UPDATE:
After following your advice I came up with this
$ids = [30,32,33,44];
$questionMarks = rtrim(str_repeat('?,',count($ids)),", ");
$parameters = str_repeat('i',count($ids));
echo $questionMarks."<br>";
echo $parameters."<br>";
$stmt = $mysqli->prepare("
SELECT `title` from `MY_TABLE` WHERE id in (".$questionMarks.")
");
$scene_names = [];
$stmt->bind_param($parameters, $ids); //error here
$stmt->execute();
$stmt->bind_result($title);
$stmt->store_result();
I am still getting an error. This time it says:
Number of elements in type definition string doesn't match number of bind variables
I am not sure why it thinks that the number of elements (what is element in this case?) is wrong.
UPDATE 2:
Instead of:
$stmt->bind_param($parameters, $ids); //error here
I used:
$stmt->bind_param($parameters, ...$ids); //error gone
Taraam. Works fine.
Something like:
$ids = [30,32,33,44];
$types = array();
foreach($ids as $i){
array_push($types,'i');
}
$params = array_merge($ids,$types);
$sqlIN = str_repeat('?,',count($ids));
$sqlIN = rtrim($sqlIN, ',');
//Value of $sqlIN now looks like ?,?,?,?
$sql = "SELECT title from MY_TABLE WHERE id IN ($sqlIN)";
$stmt = $mysqli->prepare($sql);
call_user_func_array(array($stmt, 'bind_param'), $params);
$stmt->execute();
$stmt->bind_result($id);
$stmt->store_result();
Yesterday i decided to learn PDO and rewrite our server php to PDO.
The thing that jumped to my mind while rewriting the code is the need of repeated use of bindParam for the same parameters i already used.
Here is an example:
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->beginTransaction();
$stmt = $dbh->prepare("INSERT INTO Products(productID,numOfLikes) VALUES (:productID,0) ON DUPLICATE KEY UPDATE productID = productID;");
$stmt->bindParam(":productID",$productID);
$stmt->execute();
if($customerID !== 0){
//*****Check, if customerID is in the Database, else add the customerID to the Database.
$stmt = $dbh->prepare("INSERT INTO Customers(customerID) VALUES (:customerID) ON DUPLICATE KEY UPDATE customerID = customerID;");
$stmt->bindParam(":customerID",$customerID);
$stmt->execute();
//*****if customerID and productID are NOT registered together ,then register and add +1 to productID numOfLikes
$stmt = $dbh->prepare("SELECT customerID, productID FROM CustomerProducts WHERE productID = :productID AND customerID = :customerID");
$stmt->bindParam(":productID",$productID);
$stmt->bindParam(":customerID",$customerID);
$stmt->execute();
if ($stmt->rowCount() == 0) {
//echo "added";
$stmt = $dbh->prepare("INSERT INTO CustomerProducts(customerID, productID) Values (:customerID,:productID)");
$stmt->bindParam(":customerID",$customerID);
$stmt->bindParam(":productID",$productID);
$stmt->execute();
$stmt = $dbh->prepare("UPDATE Products SET numOfLikes = numOfLikes + 1 WHERE productID = :productID");
$stmt->bindParam(":productID",$productID);
$stmt->execute();
}else {
//echo "removed";
$stmt = $dbh->prepare("DELETE FROM CustomerProducts WHERE productID = ".$productID." AND customerID = ".$customerID);
$stmt->bindParam(":customerID",$customerID);
$stmt->bindParam(":productID",$productID);
$stmt->execute();
$stmt = $dbh->prepare("UPDATE Products SET numOfLikes = numOfLikes - 1 WHERE productID = ".$productID);
$stmt->bindParam(":productID",$productID);
$stmt->execute();
}
}
$dbh->commit();
Is there a way to write it in "prettier way"?
Can you see any flows in that could. I would appreciate every help.
Note: this code will be for production use in the near future.
Yes there is...
You can supply bindParam as an array to the execute function...
Something like this:
$statement->execute([
':username'=> $username,
':password'=> $password
]);
It's using bindParam and execute in just one statement, and it looks cleaner in my opinion.
Yes, you can get around the repeated variables by defining mySql user variables like this:
$psVars = $dbh->prepare("SET #pid = :productID;");
$psVars->bindParam(':productID', $productID);
$psVars->execute();
Then, in subsequent statements, just use #pid instead of a bound parameter
This is the code that makes the error:
$sql = 'INSERT INTO pedidos (pagado, instalado) VALUES ("'.$_POST['email'].'", "'.$_POST['b'].'") WHERE email="'.$_POST['2'].'"';
$stm = $conn->prepare($sql);
$conn->exec($stm);
That's not the proper way to use prepare and execute. The reason this was created was so that you wouldn't need to put logic and data together and put yourself at risk of an SQL injection attack.
$sql = 'INSERT INTO pedidos (pagado, instalado) VALUES (:pagado, :instalado)';
$stm = $conn->prepare($sql);
$stm->bindParam(':pagado', $_POST['email']);
$stm->bindParam(':instalado', $_POST['b']);
$stm->execute();
It also doesn't make sense to put a WHERE in an INSERT query. You're inserting into your table, you're not getting data.
However, if you're updating data based on other data, then you should use an UPDATE query.
UPDATE pedidos SET pagado=?, instalado=? WHERE email=?
An example of this would be:
$sql = 'UPDATE pedidos SET pagado=:padago, instalado=:instalado WHERE email=:email';
$stm = $conn->prepare($sql);
$stm->bindParam(':pagado', $_POST['email']);
$stm->bindParam(':instalado', $_POST['b']);
$stm->bindParam(':email', $_POST['2']);
$stm->execute();
UPDATE - 2:
$sql = 'INSERT INTO pedidos SET pagado = ?, instalado = ? WHERE email = ?';
$stm = $conn->prepare($sql);
$stm->bindParam(1,$_POST['email']);
$stm->bindParam(2,$_POST['b'] );
$stm->bindParam(3,$_POST['2'] );
$stm->execute(); // here your code generate error
Reason: You put $stm in execute() , which makes an error.
I am currently trying to run a query where the current value of a mysql table column increase itself by 1... Let me show this with mysql query example
$sql = mysql_query("UPDATE `table` SET quantity=quantity+1 WHERE id='$id'");
I am unable to do this in PDO prepared statement...
$sql = "UPDATE `table` SET quantity=:quants+1 WHERE id=:userid";
$sql_prep = $db->prepare($sql);
$sql_prep->bindParam(":quants", what will i write here??);
$sql_prep->bindParam(":userid", $id);
$sql_prep->execute();
Help needed..! Thanks
You don't need to pass that as a parameter, just do:
$sql = "UPDATE `table` SET quantity=quantity+1 WHERE id=:userid";
$sql_prep = $db->prepare($sql);
$sql_prep->bindParam(":userid", $id);
$sql_prep->execute();
You don't need the to protect quantity as you're just augmenting a value already in the db.
$sql = "UPDATE `table` SET quantity=quantity+1 WHERE id=:userid";
You can also drop the bind line for the :quants
$sql_prep = $db->prepare($sql);
// NOT NEEEDED --> $sql_prep->bindParam(":quants", what will i write here??);
$sql_prep->bindParam(":userid", $id);
$sql_prep->execute();
Prepared statements are for protecting data being inserted from the outside into your db via your query.