i noticed that when posting a form the fields come out as an array.
like if i do
if(isset($_POST['submit'])) {
print_r($_POST);
}
what i usually do for form fields is the following.
lets say i have something like this (this is how i usually do it)
<form method="POST" action="">
<label>First Name: </label>
<input type="text" name="fname">
<label>Last Name: </label>
<input type="text" name="lname">
<label>Phone: </label>
<input type="text" name="phone">
<input type="submit" name="submit" value="submit">
</form>
then i'll have (im excluding field validation to make it look clear)
if(isset($_POST['submit'])) {
$fname = $_POST['fname'];
$lname = $_POST['lname'];
$phone = $_POST['phone'];
mysql_query("insert into table(fname,lname,phone) values('$fname','$lname','$phone')");
header("Location: gosomewhere.php");
}
since the post outputs are in an array format how else can i write this when im dealing with over 100 fields?
how are the big guys doing it out there? or how are you doing it?
edit: the most ive dealth with is around 60 fields. im building this cms that takes in alot of data per form to put together information from a customer.
I don't think I've ever seen anybody "dealing with over 100 fields" in a single form. If that is the case, you may consider a design-change that auto-saves portions of the data along the way. Form data will always submit itself into an array on the server-end, there's no way around this.
If you want to iterate over many fields all at once (suppose you are accepting multiple event-dates in your form), you could use the array-style naming-convention:
<input type="text" name="events[]" />
Once you access this data on the server end, you can iterate over it quickly in a simple loop:
foreach ($_POST["events"] as $event) {
echo $event;
}
I'm sorry if I missunderstood your question.
As Jonathan said, 100 fields in one form is way to much. But you can always build the SQL dynamically.
E.g:
if(isset($_POST['submit'])) {
// allow only entries that are database fields
$allow = array(/*whatever*/);
$fields = array();
$values = array();
foreach($_POST as $field => $value) {
if(in_array($field, $allow) {
// Do correct output escaping etc. here !!
$fields[] = $field;
$values[] = mysql_real_escape_string($value);
}
}
mysql_query('insert into table(' . join(',', $fields) . ' values(' . join(',', $values) . ')');
}
This assumes that your form fields names are the same as your DB column names.
If, as Cyro says, array_keys and array_values preserve order, then this can be done even nicer:
function clean($value, $field, &$params) {
if(in_array($field, $params['allow']) {
// custom validation goes here
$params['data'][$field] = mysql_real_escape_string($value);
}
}
if(isset($_POST['submit'])) {
// allow only entries that are database fields
$allow = array(/*whatever*/);
$params = array('allow' => $allow, 'data' => array());
array_walk($_POST, 'clean', $params);
if(!empty($params['data'])) {
mysql_query('insert into table(' . join(',', array_keys($params['data'])) . ' values(' . join(',', array_values($params['data'])) . ')');
}
}
See array_walk
If your form contains over 100 fields, I'd worry much more about the client side than the server side. Consider using something like jQuery UI Tabs to split the form up into multiple areas, separated using fieldsets, to enhance usability.
One way around the array issue would be to use something like PHP's extract function, but I wouldn't recommend this for security reasons, and because it wouldn't really make the data any easier to work with.
The best way of dealing with so many fields is to reduce the number of fields. No one wants to have to fill out scores of fields.
Failing that, PDO has much to offer by supporting prepared statements. One thing are parameters, which (unlike your sample code) aren't vulnerable to SQL injection. Parameters can also be used to more easily construct a query using values from an array.
$query = $db->prepare("INSERT INTO table (surname, given_name, main_phone, ...)
VALUES (:fname, :lname, :phone, ...)");
$values = array()
foreach($_POST as $key => $val) {
$values[':' + $key] = $val;
}
try {
$query->execute($values);
} catch (PDOException $exc) {
...
}
The list of column names can be defined elsewhere, or automatically generated, then imploded when creating the prepared statement.
If your form field names directly relate to your database table columns you can dynamically build your query from the $_POST array. From your example you could do:
$allowed_fields = array('fname', 'lname', 'phone');
foreach($_POST as $key => $value) {
// if this isn't an expected field (user-injection) ignore it
if(!in_array($key, $allowed_fields))
continue;
// do validation checks and data clean up here in a switch
$data[$key] = mysql_real_escape_string($value);
}
mysql_query("INSERT INTO table(`" . implode('`, `', array_keys($data)) . "`) VALUES('" . implode("', '", array_values($data)) . "')");
Really though, a form with 100+ fields is not something I would ever fill out and I don't believe I'm alone in that. Consider breaking it up into multiple steps as others have suggested or try re-approaching your initial design.
Related
I am trying to filter some inputs of the user with select boxes. I am figuring if there is a better way doing this.
if(isset($_POST['action']))
{
$sql = "SELECT * FROM occasions WHERE naam IS NOT NULL";
if(isset($_POST['merk'])){
$merk = $_POST['merk'];
$merkQuery = implode(',', array_fill(0, count($merk), '?'));
$sql .= " AND merk IN(".$merkQuery.")";
}
if(isset($_POST['brandstof'])){
$brandstof = $_POST['brandstof'];
$brandstofQuery = implode(',', array_fill(0, count($brandstof), '?'));
$sql .= " AND brandstof IN(".$brandstofQuery.")";
}
//We prepare our SELECT statement.
$statement = $pdo->prepare($sql);
if(isset($_POST['merk'])){
//Execute statement.
$statement->execute(array_merge(array_values($merk)));
}
if(isset($_POST['brandstof'])){
//Execute statement.
$statement->execute(array_merge(array_values($brandstof)));
}
if(isset($_POST['merk']) && isset($_POST['brandstof']))
{
$statement->execute(array_merge(array_values($merk), array_values($brandstof)));
}
else
{
$statement->execute();
}
}
Cause if there are many select boxes that need filtering, the code would become long. I was wondering if there is a better way of filtering multiple select boxes.
Here is an example: link
I would suggest renaming the post variables; grouping them into a single two dimensional array.
<input type="checkbox" name="data[merk][bmw]" />
<input type="checkbox" name="data[merk][skoda] />
and so forth.
What this does, is it allows you to use a foreach to iterate through whatever values are checked.
$data = $_POST['data'] ?? []; // null coalesce defaults to a blank array if post var is null
foreach($data as $category=>$val) {
settype($val, 'array');
$query = implode(',', array_fill(0, count($val), '?'));
foreach($val as $k=>$v) {
$params[] = $k;
}
// DON'T DO THIS!
$sql .= " AND $category IN(".$query.")";
}
The reason you shouldn’t do it as shown is because you should never build a query with user-supplied data.
What you can do, however, is map user-supplied data with hard-coded data.
$map = [
// form value => db field
'merk' => 'MERK',
'brandstof' => 'BRANDSTOF',
// ... etc
];
and then when building your query,
$sql .= " AND $map[$category] IN($query)";
In the meantime, you have built your parameters in $params.
—-
Bottom line, what we have done is refactor the code since we were noticing things getting repeated. For example, you were having to repeat code for each occasion(?). One solution would be to continue to check each post value and call a function to calculate the ?s. But even then, it would be repetitive to type out all those isset()s.
In retrospect, it probably would have been better to do inputs like this:
<input type="checkbox" name="data[merk][]" value="bmw" />
<input type="checkbox" name="data[merk][]" value="skoda" />
This would no doubt be more intuitive, although you would still have to build the params array.
foreach($val as $v) {
$params[] = $v;
}
Here is my PHP variable:
$container = $_POST['containerNumber'];
Inside $_POST['containerNumber'], there are multiple container numbers that are retrieved when a user checks a checkbox from a form. That code is not necessary to display. Just know that $_POST['containerNumber'] can have multiple container numbers assigned to it.
What I need to do is extract each container number from the POST so that I can run a mysql INSERT statement per each container number.
In the database table, there are multiple columns, with container_num being the column I'm trying to update (for now).
How can I turn $container into an array and retrieve each container number that has been assigned to the variable?
I know I need to utilize a FOREACH loop. With that said, there will more than likely be multiple INSERT statements that will automatically be created with the loop.
$SQL = "INSERT INTO myTable (container_num) VALUES ('$container')";
// times however many containers the variable $container had stored in it
Please help.
EDIT **
Once the user checks however many checkboxes, I can display each container like this:
<INPUT name="containerNumber" id="containerNumber" class="containerNumber" />
When I do this, it can be displayed to the screen like this:
CONT_ID001, CONT_ID002, CONT_ID003...
I hope this helps.
There are multiple ways of doing this.
1) Give the POST parameters you're sending a name that ends with [], PHP automatically assigns them to an array when parsing the POST data. If you're sending the data from an HTML form, this is an example of how to do it:
<form action="" method="POST">
<label>
First container number:
<input type="text" name="containerNumber[]" />
</label>
<label>
Second container number:
<input type="text" name="containerNumber[]" />
</label>
<input type="submit" />
In PHP you can just do
foreach($_POST["containerNumber"] as $container) {
...
}
(Note that this is a feature of PHP and not portable to other server-side langages. This is NOT part of the HTTP specification.)
2) Separate values using some separator, in PHP use explode() to split it.
3) Send the form as JSON or encode that one field as JSON (if sent from HTML, I suggest using jQUery to do either option, as it's the easiest way) and use json_decode() in PHP to extract the contents.
4) Sevaral other options that may be suitable, depending on what exactly you're doing.
If I get you, you have a $_POST variable with multiple values.
If the content of $_POST['containerNumber'] is CONT_ID001, CONT_ID002, CONT_ID003
You can do this:
$result = preg_split("/, /", $_POST['containerNumber']);
//the result dump will be:
//$result[0] = "CONT_ID001";
//$result[1] = "CONT_ID002";
//$result[2] = "CONT_ID003";
The insert code should looks like to (assuming that you have one column for each number):
$SQL = "INSERT INTO myTable ";
$columns = "";
$values = "";
foreach (result as $id=>$out){
$columns .= "container_$id";
$values .= "'$out'";
if (count($result) < $id+1){
$columns .= ", ";
$values .= ", ";
}
}
$SQL .= "($columns) VALUES ($values)";
If you only have container_num column it should looks like:
$SQL = "INSERT INTO myTable (container_num) VALUES ('";
$columns = "";
$values = "";
foreach (result as $id=>$out){
$values .= $out;
if (count($result) < $id+1){
$values .= ", ";
}
}
$SQL .= "$values')";
I have a dynamic form that populates a questionnaire rating scale from information saved in my database. Each rating consists of a "selection" and a "definition". A scale can consists of any number or ratings. Here is an example of a 5 rating scale:
Strongly Agree = I strongly agree with this statement.
Agree = I agree with this statement.
Neither Agree nor Disagree = I neither agree nor disagree with this statement.
Disagree = I disagree with this statement.
Strongly Disagree = I strongly disagree with this statement.
Once the form is populated, the user can edit any of the selections or definitions. My form populates just fine, but I cannot figure out how to correctly populate the POST data into an array if the user submits a change or use that array to edit the information in my database.
Here is my PHP:
if(isset($_POST['submit'])){
$fields = "";
$values = "";
foreach($_POST as $key => $value) {
$fields = mysql_real_escape_string($key);
$values = mysql_real_escape_string($value);
$entry .= "[". $fields . "=" . $values . "]";
//Here is the start of the query that I'm building
//$query = mysql_query("UPDATE `pd_selections` SET `pd_selection` = ' ', `pd_definition` = ' ' WHERE `pd_selection_id` = '$pd_selection_id' ") or die(mysql_error());
}
}
If I echo the "entry" variable, this is what I receive:
[selection_for_1=Strongly Agree][definition_for_1=I strongly agree with this statement.][selection_for_2=Agree][definition_for_2=I agree with this statement.]
How do I pull the selection and the definition out of the array for each rating?
How is that used to update the database?
Am I even on the right track...LOL!?
Thank you very much for any help you can provide.
For security purpose you should keep a list of keys you would accept to prevent the user from modifying it, this will keep people from adding non valid data to your form as well as keeping out fields you may not want.
Create an array for selection another for definition, and use it to store the key/value while checking for valid fields:
$accept = array('selection_for_1', 'definition_for_1',
'selection_for_2', 'definition_for_2');
$selection = array();
$definition = array();
foreach ($_POST as $key => $value)
{
// if not valid go to next field/value
if(!in_array($key, $accept))
continue;
// if start with selection save to $selection array
// otherwise to definition array
if (strpos($key, 'selection') !== false)
{
$selection[] = mysql_real_escape_string($value);
}
else
{
$definition[] = mysql_real_escape_string($value);
}
}
// count one of the array to select the paired fields
// and insert or update into database
$total = count($definition);
for ($i=0; $i < $total; $i++)
{
// Update query for the paired selection and definition
$query = mysql_query("UPDATE pd_selections
SET pd_selection = '{$selection[$i]}',
pd_definition = '{$definition[$i]}'
WHERE pd_selection_id = '{$pd_selection_id}'")
or echo("Could not insert or update selection '{$selection[$i]}', definition '{$definition[$i]}', failed with error:", mysql_error());
}
Live DEMO.
I thought I would edit my question as by the comment it seems this is a very insecure way of doing what I am trying to acheive.
What I want to do is allow the user to import a .csv file but I want them to be able to set the fields they import.
Is there a way of doing this apart from the way I tried to demonstrate in my original question?
Thank you
Daniel
This problem I am having has been driving me mad for weeks now, everything I try that to me should work fails.
Basically I have a database with a bunch of fields in.
In one of my pages I have the following code
$result = mysql_query("SHOW FIELDS FROM my_database.products");
while ($row = mysql_fetch_array($result)) {
$field = $row['Field'];
if ($field == 'product_id' || $field == 'product_name' || $field == 'product_description' || $field == 'product_slug' || $field == 'product_layout') {
} else {
echo '<label class="label_small">'.$field.'</label>
<input type="text" name="'.$field.'" id="input_text_small" />';
}
}
This then echos a list of fields that have the label of the database fields and also includes the database field in the name of the text box.
I then post the results with the following code
$result = mysql_query("SHOW FIELDS FROM affilifeed_1000.products");
$i = 0;
while ($row = mysql_fetch_array($result)) {
$field = $row['Field'];
if ($field == 'product_name' || $field == 'product_description' || $field == 'product_slug' || $field == 'product_layout') {
} else {
$input_field = $field;
$output_field = mysql_real_escape_string($_POST[''.$field.'']);
}
if ($errorcount == 0) {
$insert = "INSERT INTO my_database.products ($input_field)
VALUES ('$output_field')";
$result_insert = mysql_query($insert) or die ("<br>Error in database<b> ".mysql_error()."</b><br>$result_insert");
}
}
if ($result_insert) {
echo '<div class="notification_success">Well done you have sucessfully created your product, you can view it by clicking here</div>';
} else {
echo '<div class="notification_fail">There was a problem creating your product, please try again later...</div>';
}
It posts sucessfully but the problem is that it creates a new "row" for every insert.
For example in row 1 it will post the first value and then the rest will be empty, in row 2 it will post the second value but the rest will be empty, row 3 the third value and so on...
I have tried many many many things to get this working and have researched the foreach loop which I haven't been familiar with before, binding the variable, imploding, exploding but none of them seem to do the trick.
I can kind of understand why it is doing it as it is wrapped in the while loop but if I put it outside of this it only inserts the last value.
Can anyone shed any light as to why this is happening?
If you need any more info please let me know.
Thank you
Daniel
You're treating each field you're displaying as its own record to be inserted. Since you're trying to create a SINGLE record with MULTIPLE fields, you need to build the query dynamically, e.g.
foreach ($_POST as $key => $value);
$fields[] = mysql_real_escape_string($key);
$values[] = "'" . msyql_real_escape_string($value) . "'";
} // build arrays of the form's field/value pairs
$field_str = implode(',', $fields); // turn those arrays into comma-separated strings
$values_str = implode(',', $values);
$sql = "INSERT INTO yourtable ($field_str) VALUES ($value_str);"
// insert those strings into the query
$result = mysql_query($sql) or die(mysql_error());
which will give you
INSERT INTO youtable (field1, field2, ...) VALUES ('value1', 'value2', ...)
Note that I'm using the mysql library here, but you should avoid it. It's deprecated and obsolete. Consider switching to PDO or mysqli before you build any more code that could be totally useless in short order.
On a security basis, you should not be passing the field values directly through the database. Consider the case where you might be doing a user permissions management system. You probably wouldn't want to expose a "is_superuser" field, but your form would allow anyone to give themselves superuser privileges by hacking up their html form and putting a new field saying is_superuser=yes.
This kind of code is downright dangerous, and you should not be using it in a production system, no matter how much sql injection protect you build into it.
Alright....I can't say that I know exactly whats going on but lets try this...
First off....
$result = mysql_query("SHOW FIELDS FROM my_database.products");
$hideArray = array("product_id","product_name","product_description", "product_slug","product_layout");
while ($row = mysql_fetch_array($result)) {
if (!in_array($row['Field'], $hideArray)){
echo '<label class="label_small">'.$field.'</label>
<input type="text" name="'.$field.'" id="input_text_small" />';
}
}
Now, why you would want to post this data makes not sense to me but I am going to ignore that.....whats really strange is you aren't even using the post data...maybe I'm not getting something....I would recommend using a db wrapper class...that way you can just through the post var into....ie. $db->insert($_POST) ....but if you ware doing it long way...
$fields = "";
$values = "";
$query = "INSERT INTO table ";
foreach ($_POST as $key => $data){
$values .= $data.",";
$fields .= $fields.",";
}
substr($values, 0, -1);
substr($fields, 0, -1);
$query .= "(".$fields.") VALUES (".$values.");";
This is untested....you can also look into http://php.net/manual/en/function.implode.php so you don't have to do the loop.
Basically you don't seem to understand what is going on in your script...if you echo the sql statements and you can a better idea of whats going....learn what is happening with your code and then try to understand what the correct approach is. Don't just copy and paste my code.
Suppose I've a large form, 25 fields consisting of textboxes, radio buttons, checkboxes, select tags, textareas etc.
Once the form is submitted, what would be the best way to collect those values and then store them into database; by best practice I mean using as minimal lines of code as possible.
There is the traditional way:
$name = $_POST['name'];
$age = $_POST['age'];
$city = $_POST['city'];
which is definitely not the way to go.
There is then another way :
foreach($_POST['submit'] as $key=>$val)
{
$$key = $val;
}
but again this will require a huge INSERT SQL statement:
"INSERT INTO tablename (col1, col2, col3, col4,...col25)
VALUES('$var1', '$var2', '$var3',.....'$var25')"
Using foreach to capture values is good, but then it comes with an elongated SQL INSERT statement. I'm sure there must a better way to use the INSERT statement. Ideas, suggestions, critics are all welcome.
Thanks,
Nisar
You don't need that traditional way, you can use extract function like:
extract($_POST);
This will make all indexes as variables with values.
In other way, to store in database, you can either serialize values or store in JSON format. And then store whole form values as single entry in DB (if there is nothing relational and purpose is only to store values.)
In HTML change as follows
<input type="text" name="pval[name]" value="test" />
<input type="city" name="pval[city]" value="Bangalore" />
Then in the server side
Updated :
// Need to have the predefined array which is having valid fields
$fields = array('name', 'city');
$pval = $_POST['pval'];
foreach( $pval as $field_name => $val ){
if( ! isset($fields[$field_name]) ){ // If it is not a valid field name
unset($pval[$field_name]);
}
}
if( count($pval) > 0 ){
$pval = array_map( 'mysql_real_escape_string', $pval );
//Then its easy to write the query as follows
$qry = "INSERT INTO table_name( ". implode( ',', array_keys( $pval ) ) .") values( '". implode( "','", $pval ) . "')";
}