Reputation: 127
I have this awesome loop from a question I asked yesterday. Previously, I could use mysql_real_escape_string($val) and that would handle protection against injection attacks and such. With PDO, however, there is not quite as simple of a function.
What can I do?
if (($_GET['mode'] == "update") and isset($_GET['id']) and isset($_POST['who'])) {
$query = "update subcontractors set";
$comma = " ";
$whitelist = array("firstname","lastname","address","city","state","zip","phone1","phone2","phone3","email","dob","ssn","website","checks");
foreach($_POST as $key => $val) {
if ( !empty($val) && in_array($key, $whitelist)) {
$query .= $comma . $key . "='" . $val . "'";
$comma = ", ";
}
}
$query .= " where id=" . $_POST['who'];
include "connect.php";
$db->query($query);
} #endif UPDATE SECTION
Upvotes: 0
Views: 115
Reputation:
Since there are too many parameters and too many forms and databases then it might be best to create some stored procedures and call each one depending the case/form being submitted. As for the above example i would go for a not dynamic solution in this case. Only because a field in your whitelist array could be a MySQL reserved keyword something that it would cause an error when the MySQL server executes your query.
if (($_GET['mode'] == "update") and isset($_GET['id']) and isset($_POST['who'])) {
include "connect.php";
$stmt = dbh->prepare("UPDATE `subcontractors` SET `firstname`=:firstname,`lastname`=:lastname,`address`=:address,`city`=:city,`state`=:state,`zip`=:zip,`phone1`=:phone1,`phone2`=:phone2,`phone3`=:phone3,`email`=:email,`dob`=:dob,`ssn`=:ssn,`website`=:website,`checks`=:checks WHERE `id`=:id");
$stmt->bindParam(':firstname', $_POST['firstname']);
$stmt->bindParam(':lastname', $_POST['lastname']);
$stmt->bindParam(':address', $_POST['address']);
$stmt->bindParam(':city', $_POST['city']);
$stmt->bindParam(':state', $_POST['state']);
$stmt->bindParam(':zip', $_POST['zip']);
$stmt->bindParam(':phone1', $_POST['phone1']);
$stmt->bindParam(':phone2', $_POST['phone2']);
$stmt->bindParam(':phone3', $_POST['phone3']);
$stmt->bindParam(':email', $_POST['email']);
$stmt->bindParam(':dob', $_POST['dob']);
$stmt->bindParam(':ssn', $_POST['ssn']);
$stmt->bindParam(':website', $_POST['website']);
$stmt->bindParam(':checks', $_POST['checks']);
$stmt->bindParam(':id', $_POST['who']);
$stmt->execute();
} #endif UPDATE SECTION
Upvotes: 1
Reputation: 1630
I changed the code in several small ways:
In the loop, it is now building a prepared statement instead of a full query. I replaced the $val variable that was being inserted into the sql statement with a "?" placeholder.
$query .= $comma . $key . "= ?";
In the loop, I place the $val into an array that will later be used to bind to the placeholders when the statement is executed.
$params[] = $val;
I call the prepare method of the PDO object and pass it the $query variable as an argument:
$sth = $db->prepare($query);
I call the execute method on the $sth (which is an object of the PDOStatement class) and pass it the $param array as an arguement. It will bind the array values to the placeholders in order:
$sth->execute($params);
This will protect you from injection.
if (($_GET['mode'] == "update") and isset($_GET['id']) and isset($_POST['who'])) {
$query = "update subcontractors set";
$comma = " ";
$params = array();
$whitelist = array("firstname","lastname","address","city","state","zip","phone1","phone2","phone3","email","dob","ssn","website","checks");
foreach($_POST as $key => $val) {
if ( !empty($val) && in_array($key, $whitelist)) {
$query .= $comma . $key . "= ?";
$params[] = $val;
$comma = ", ";
}
}
$query .= " where id=?";
$params[] = $_POST['who'];
include "connect.php";
$sth = $db->prepare($query);
$sth->execute($params);
} #endif UPDATE SECTION
For more info on prepared statements with PDO please read the following:
http://php.net/manual/en/pdo.prepare.php
Upvotes: 2
Reputation: 1117
$query .= $comma . $key . "=" . $db->quote($val);
this escapes the string and the single quotes are added automatically
Upvotes: 0