Quicker way of sanitising and constructing query from PHP posted form
I have a form which has over 100 fields (most of which are checkboxe开发者_StackOverflow中文版s) and although not every field is always filled in, a large number will be. The thought of typing out each field to sanitise and construct the MySQL query is making me weep so I figure there must be a way to do this using a PHP loop.
I have managed to sanitise the form without writing out every element in the $_POST array and have it stored in $formarray in the form of $key=>$value. $key is not numerical or sequential and needs to be retained. The value of $key is the same as the column name in the database table that $value will be written to.
I want to be able to construct the MySQL query to insert the contents of $formarray into the MySQL table using a PHP loop. Is this possible?
It is possible, but not recommended, unless you are very careful. Making this loop approach secure may consume as much time as doing all the typing for all form fields, but your solution will be more roboust and modular.
You should create a mapping array wich contains directives on validating and formatting a certain value, something like this:
$validator = array(
'user_name' => array('mask' => "'%s'", 'escape' => true, 'boolean' => false),
'user_age' => array('mask' => "%d", 'escape' => false, 'boolean' => false),
'has_car' => array('mask' => "%d", 'escape' => false, 'boolean' => true)
);
Then you iterate this validator array, and check if the key exists in your posted data, and apply the directives on the value, and collect all the SQL sets in a separate array:
$set = array();
foreach ($_POST as $key => $dirs)
{
if ($dirs['boolean'])
{
$val = isset($_POST[$key]) ? 1 : 0;
$set[] = sprintf("%s=".$dirs['mask'],$key,$val);
}
elseif (isset($_POST[$key]))
{
$val = $dirs['escape'] ? addslashes($_POST[$key]) : $_POST[$key];
$set[] = sprintf("%s=".$dirs['mask'],$key,$val);
}
}
After this you can create the query by imploding the set:
$sql = "INSERT INTO table SET ".implode(",",$set);
My approach above may not suite you actual needs, but is more of a concept you can use to handle large forms on server side. You can define more complex validatons, and make it handle arrays too, not just checkboxes and text fields like this example.
Always be on your guard, your form is the fornt door to your precious data, and if you go cheap, you'll be sorry!
You may want to look into using PDO and prepared statements. One of the great things about it is that it will handle escaping "questionable" characters for you.
You could create a whitelist of columns by getting the column names directly from the database. You can then validate your posted fields against that list. Using prepared statements via PDO, you can easily build up an SQL statement to do the insert. Prepared statements save you from having to escape your data, but you will probably want to perform some validation prior to inserting the values into the database.
Should you need it, the SHOW COLUMNS
statement provides other information about the columns, so you could, for example, use it to grab only BOOL
columns.
Here's a completely untested example:
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
$valid = array();
foreach($dbh->query('SHOW COLUMNS FROM mytable') as $col) {
$field = $col['Field'];
if( isset($_POST[ $field ]) ) {
// Insert suitable validation here.
$validated_value = get_validated_value( $_POST[ $field ] );
$valid[ $field ] = $validated_value;
}
}
$cols = implode(',', array_keys($valid));
$params = implode(',', array_fill(0, count($valid), '?'));
$sql = "INSERT INTO mytable ($cols) VALUES ($params)";
$stmt = $dbh->prepare( $sql );
$stmt->execute( array_values($valid) );
精彩评论