Inserting data to the database with dynamic fields

Viewed 1792

I am working with dynamic text boxes.

I want to add the data that is entered in the text boxes to my database.

My markup:

<form name="reaction" id="reaction" method="post" action="./send.php">
    <input type="text" name="number[]" id="number1" value="15" placeholder="Number 1" /> <br />
    <input type="text" name="name[]" id="name1" value="aaaa" placeholder="Name 1" /> <br />
    <input type="text" name="price[]" id="price1" value="10" placeholder="Price 1" /> <br />
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script>
        $(document).on('click', '#add_row', function(){
            count++;
            $('#total_item').val(count);
            var html_code = '';
            html_code += '<input type="text" placeholder="Number '+count+'" name="number[]" id="number'+count+'" data-srno="'+count+'" /><br />';
            html_code += '<input type="text" placeholder="Name '+count+'" name="name[]" id="name'+count+'" data-srno="'+count+'" /><br />';
            html_code += '<input type="text" placeholder="Price '+count+'" name="price[]" id="price'+count+'" data-srno="'+count+'" /><br />';
            html_code += '<button type="button" name="remove_row" id="'+count+'" class="btn btn-danger btn-xs remove_row">X</button><br />';
        });
    </script>
    <button type="submit" class="btn btn-primary" name="send">Save</button>
</form>

Which results in the following document fragment:

<form name="reaction" id="reaction" method="post" action="./send.php">
    <input type="text" name="number[]" id="number1" value="15" placeholder="Number 1" /> <br />
    <input type="text" name="name[]" id="name1" value="aaaa" placeholder="Name 1" /> <br />
    <input type="text" name="price[]" id="price1" value="10" placeholder="Price 1" /> <br />
    <input type="text" name="number[]" id="number2" value="12" placeholder="Number 2" /> <br />
    <input type="text" name="name[]" id="name2" value="bbbb" placeholder="Name 2" /> <br />
    <input type="text" name="price[]" id="price2" value="15" placeholder="Price 2" /> <br />
    <input type="text" name="number[]" id="number3" value="38" placeholder="Number 3" /> <br />
    <input type="text" name="name[]" id="name3" value="cccc" placeholder="Name 3" /> <br />
    <input type="text" name="price[]" id="price3" value="29" placeholder="Price 3" /> <br />
    <button type="submit" class="btn btn-primary" name="send">Save</button>
</form>

When submitting the form I want to add the following data to the database:

| session_id  |  number  |   name   |   price  |
|-------------|----------|----------|----------|
|      1      |    15    |   aaaa   |    10    |
|      1      |    12    |   bbbb   |    15    |
|      1      |    38    |   cccc   |    29    |

In my PHP code I am using the following to define the text boxes:

foreach($_POST['number'] as $i => $item) {

When I execute the script I only get the data of the first three textboxes. I get in my database:

| session_id  |  number  |   name   |   price  |
|-------------|----------|----------|----------|
|      1      |    15    |   aaaa   |    10    |

After weeks of doing research I have discovered that there is something wrong with the JavaScript part of the code. When I send the data with the text boxes in the second example I get the result I want. When I use JavaScript to create the dynamic text boxes the PHP script will only post the first row (that is not created with JavaScript) to the database.

What is wrong with my script?

Here is the script I am using to add data to my database:

<?php
    $correct = true;
    $_SESSION['session_id'];
    $number = $_POST['number'] ;
    $name = $_POST['name'] ;
    $price = $_POST['price'] ;
    if($correct){
        foreach($_POST['number'] as $i => $item) {
            $db = new PDO('mysql:host=localhost;dbname=db', 'user', 'pass');
            $query= "INSERT INTO products(session_id, number, name, price) VALUES (:session_id, :number, :name, :price)";
            $stmt = $db->prepare($query);
            $exec = $stmt->execute(array(
                ':session_id' => $_SESSION['session_id'],
                ':number' => $_POST["number"][$i],
                ':name' => $_POST["name"][$i],
                ':price' => $_POST["price"][$i]
            ));
        }
    }
    else
    {
        header('Location: ../error.php');
    }
?>

Result of var_dump on $_POST['number']:

array(1) { [0]=> string(2) "15" }
3 Answers

The main problem is that all your fields in the form have the same name, even though they are supposed to be arrays, you're not really allowing for multiple rows.

The easiest (not necessarily the optimal) way is to make some tweaks

Change your form element names to

variable[$i][number]
variable[$i][name]
variable[$i][price]

and make sure your form changes the value for $i on each row, so that your form becomes:

<form name="reaction" id="reaction" method="post" action="./send.php">
<input type="text" name="variable[0][number]" id="number1" value="15" placeholder="Number 1" /> <br />
<input type="text" name="variable[0][name]" id="name1" value="aaaa" placeholder="Name 1" /> <br />
<input type="text" name="variable[0][price]" id="price1" value="10" placeholder="Price 1" /> <br />

<input type="text" name="variable[1][number]" id="number1" value="15" placeholder="Number 1" /> <br />
    <input type="text" name="variable[1][name]" id="name1" value="aaaa" placeholder="Name 1" /> <br />
    <input type="text" name="variable[1][price]" id="price1" value="10" placeholder="Price 1" /> <br />

and so on... Then, alter your form processing to iterate over $variable:

foreach($variable as $var)
{
   $number = $var['number'];
   $name = $var['name'];
   $price = $var['price'];

   // do whatever it is you do with the variables and then loop to the next row
}

that's it! Like I said, this is not necessarily the best way to accomplish your goal, but it is by far the easiest

You can keep your form fields with the array names, but in order to post your data to the database, you will need to iterate through the array.

So your receiving page should collected all the form data in a $_POST variable, and then you can parse the posted values as $_POST['number'] and iterate through the array using a for-each loop.

foreach ($_POST['price'] as $key => $value) {
     // do something with array value
    echo "{$key} => {$value} ";

    print_r($_POST['price']);
}

Dont inject pure html but play with DOM.

<form name="reaction" id="reaction" method="post" action="./send.php">
    <button type="submit" class="btn btn-primary" name="send">Save</button><br />
</form>

<script>
function newInput(type, value, count){
    var newInput = document.createElement('input');
    newInput.type = 'text';
    newInput.name = type+'[]';
    newInput.id = type+count;
    newInput.value = value;
    newInput.placeholder = type+' '+count; // <--you probably want to camelize this
    return newInput;
}

function addRow(number, name, price, count, target){
    target.appendChild(newInput('number', number, count));
    target.appendChild(newInput('name', name, count));
    target.appendChild(newInput('price', price, count));
    target.appendChild(document.createElement('br')); // <-- create any element
}

var myForm = document.getElementById('reaction');
var count = 0;
addRow(111, 'one', 1, ++count, myForm);
addRow(222, 'two', 2, ++count, myForm);
addRow(333, 'three', 3, ++count, myForm);
addRow(444, 'four', 4, ++count, myForm);
</script>

PHP part looks almost OK:

$post_number = $_POST['number'];
$post_name = $_POST['name'];
$post_price = $_POST['price'];

//check, if needed set session variables here, then
$ses_id = session_id();

$db = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$query= "INSERT INTO products(session_id, number, name, price) VALUES (:session_id, :number, :name, :price)";

foreach($_POST['number'] as $i => $item) {
    $stmt = $db->prepare($query);
    $exec = $stmt->execute(array(
        ':session_id' => $ses_id,
        ':number' => $post_number[$i],
        ':name' => $post_name[$i],
        ':price' => $post_price[$i]
    ));
    if($exec == false)
        header('Location: ../error.php');
        //or print out what happened
        //$e = $stmt->errorInfo();
        //print_r($e);
        //die();
}
Related