HiveBrain v1.2.0
Get Started
← Back to all entries
patternphpMinor

PHP prepared statements

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
phppreparedstatements

Problem

Is this correct coding for prepared statements in php. I've done some reading but the best way to learn is criticism from peers. Any suggestions to improve this code? Anything I've done wrong? Thanks you!

```
$dbh = new PDO('mysql:host=localhost;dbname=tests;charset=UTF-8', $user, $pass);
$stmt = $dbh->prepare('INSERT INTO items (item_id,itemname,itemuni, soldby,soldby2,keywords,description,sizing,price,totalquantity,lowquantity,weight,length,width,height,imagelocation,thumblocation,fblocation,cat1,cat2,cat3,size1,quantity1,size2,quantity2,size3,quantity3,size4,quantity4,size5,quantity5,size6,quantity6,size7,quantity7,size8,quantity8,size9,quantity9,size10,quantity10,size11,quantity11,size12,quantity12,size13,quantity13) VALUES (:item_id,:itemname,:itemuni,:soldby,:soldby2,:keywords,:description,:sizing,:price,:totalquantity,:lowquantity,:weight,:length,:width,:height,:imagelocation,:thumblocation,:fblocation,:cat1,:cat2,:cat3,:size1,:quantity1,:size2,:quantity2,:size3,:quantity3,:size4,:quantity4,:size5,:quantity5,:size6,:quantity6,:size7,:quantity7,:size8,:quantity8,:size9,:quantity9,:size10,:quantity10,:size11,:quantity11,:size12,:quantity12,:size13,:quantity13)');
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt->bindValue(':item_id', '44', PDO::PARAM_STR);
$stmt->bindValue(':itemname', $_POST['itemname'], PDO::PARAM_STR);
$stmt->bindValue(':itemuni',$getitemuni, PDO::PARAM_STR);
$stmt->bindValue(':soldby', $soldby, PDO::PARAM_STR);
$stmt->bindValue(':solby2', $soldby2, PDO::PARAM_STR);
$stmt->bindValue(':keywords', $_POST['keywords'], PDO::PARAM_STR);
$stmt->bindValue(':description', $_POST['description'], PDO::PARAM_STR);
$stmt->bindValue(':sizing', 'yes', PDO::PARAM_STR);
$stmt->bindValue(':price', $_POST['price'], PDO::PARAM_STR);
$stmt->bindValue(':totalquantity', $_POST['quantity'], PDO::PARAM_STR);
$stmt->bindValue(':lowquantity',

Solution

First off, if I were about to do something this repetitive, I would set it up so that I would only have to type it all once. Best way to do this is set up an array and run it through loops. Lets start with that array.

$bindValues = array(
    'item_id' => '44',
    'itemuni' => $getitemuni,
    'soldby' => $soldby,
    etc...
);


"Wait a second! You skipped some elements and those keys are missing their colons!" Yep, DON'T add post data yet as it needs to be sanitized first. You should ALWAYS sanitize user input. Also, do not append a colon(:) to any of these array keys. You'll see why in a bit, I promise.

Now, I'm assuming you are using the entire post array. If you are not, you should either use what you need first, or set those values to a new array/variable and then unset them from the post array. Here's what you are going to do with your post array.

$filterType = array(
    'string' => FILTER_SANITIZE_STRING | FILTER_SANITIZE_STRIPPED,
    'integer' => FILTER_VALIDATE_INT,
    etc...
);

$post = array();
foreach($_POST as $key => $value) {
    $filter = $filterType[gettype($value)];
    $value = filter_var($value, $filter);
    $post[$key] => $value;
}
$bindValues = array_merge($bindValues, $post);


Here's a little explanation of what the above code does. $filterType sets up an array that will hold specific flags needed for PHP's filter_var() function. See the documentation for an explanation of this function and its flags. $post sets up a new array to add our sanitized $_POST data to. Enter the loop. $filter uses PHP's gettype() function to return the $value's type and compare it to the $filterType array for the necessary flags to use in the filter_var() function. $value is the sanitized value that you want to save to the new array. Using this new information we take the original key and sanitized value and append it to the new array. Exit loop. Merge both arrays.

Now that we are done with setup, you'll want to start the code that actually does something.

$items = implode(',', array_keys($bindValues));
$values = implode(',:', array_keys($bindValues));
/*
var_dump() these variables if you want to examine them.
Basically, this just replaces those long SQL strings you had
*/

$stmt = $dbh->prepare("INSERT INTO items ($items) VALUES (:$values)");

foreach($bindValues as $key => $value) {
    $stmt->bindValue(':' . $key, $value, PDO::PARAM_STR);
}

$stmt->execute();


Sorry if you were looking for a little more generic answer. I got a little carried away.

Code Snippets

$bindValues = array(
    'item_id' => '44',
    'itemuni' => $getitemuni,
    'soldby' => $soldby,
    etc...
);
$filterType = array(
    'string' => FILTER_SANITIZE_STRING | FILTER_SANITIZE_STRIPPED,
    'integer' => FILTER_VALIDATE_INT,
    etc...
);

$post = array();
foreach($_POST as $key => $value) {
    $filter = $filterType[gettype($value)];
    $value = filter_var($value, $filter);
    $post[$key] => $value;
}
$bindValues = array_merge($bindValues, $post);
$items = implode(',', array_keys($bindValues));
$values = implode(',:', array_keys($bindValues));
/*
var_dump() these variables if you want to examine them.
Basically, this just replaces those long SQL strings you had
*/

$stmt = $dbh->prepare("INSERT INTO items ($items) VALUES (:$values)");

foreach($bindValues as $key => $value) {
    $stmt->bindValue(':' . $key, $value, PDO::PARAM_STR);
}

$stmt->execute();

Context

StackExchange Code Review Q#11147, answer score: 6

Revisions (0)

No revisions yet.