在php中循环表单输入数组

I'm building an app in CodeIgniter. I have an invoice form which uses jQuery to create new line items. The line items are formated as follows:

<input type="text" name="invoice[new_item_attributes][][description]" class="ui-corner-all text invDesc" title="Description" />
<input type="text" name="invoice[new_item_attributes][][qty]" class="ui-corner-all text invQty" title="Qty" />
<input type="text" name="invoice[new_item_attributes][][amount]" class="ui-corner-all text invAmount" title="Amount" onChange="CalculateTotal(this.form)" />
<input type="hidden" name="invoice[new_item_attributes][][rowTotal]" class="row-total-input" />

What I can't work out is how can I loop through multiple line items to store then in a DB called line items.

At the moment i have

foreach ( $_POST['invoice'] as $key => $value)
    {
        $data = array(
            'description'   =>  $value;
                    );
    }   

But I know that can't be write because I need to somehow reference the invoice[new_item_attributes][][description] to store it in description etc...

Any help would be greatly appreciated.

The correct solution will depend on whether you plan on storing scalar values under $_POST['invoice']['new_item_attributes'] or if you plan on making it an array of arrays (in other words, you plan on having multiples of the new_item_attributes.

If you only plan on storing scalar values then you'll first need to change each of the form elements to look like this:

name="inovoice[new_item_attributes][description]"

You'll notice that the empty [] is gone.

And then your loop should look like so:

foreach($_POST['invoice']['new_item_attributes'] as $key => $val) {
    $data = array('description => $value);
}

Otherwise you'll need to use this in your PHP code:

foreach($_POST['invoice']['new_item_attributes'] as $key => $val) {
         $data = array('description' => $val['description']);
}

Or:

foreach($_POST['invoice']['new_item_attributes'] as $key => $val) {
     foreach($val as $sub => $value) {
         $data = array($sub => $value);
     }
}

My loop looks like this:

    foreach ( $_POST['invoice']['new_item_attributes'] as $key => $val ) 
   {
    $data = array(
     'description' => $val['description'],
     'qty'   => $val['qty'],
     'amount'  => $val['amount'],
     'rowTotal'  => $val['rowTotal'],
     'client_id'  => $_POST['client'],
     'company_id' => $this->session->userdata('companyID'),
     'invoice_id' => $row['id'],
       );
    $this->db->insert('line_items', $data);   
   }  

However storing each line item into the line_items table doesn't work to well. If I enter 1 line item in I get 4 entries stored in the table, and they don't seem to reflect the information inputted.

Using array append always increments the array index on assignment whether you do it in PHP or in an HTML form, so you'll end up with this:

invoice[new_item_attributes][0][description]
invoice[new_item_attributes][1][qty]
invoice[new_item_attributes][2][amount]
invoice[new_item_attributes][3][rowTotal]

If you switch your field names around so it's invoice[new_item_attributes][description][], etc, then your submitted data will look like this:

invoice[new_item_attributes][description][0]
invoice[new_item_attributes][qty][0]
invoice[new_item_attributes][amount][0]
invoice[new_item_attributes][rowTotal][0]

Which is closer to what you're after, now the fields have indexes corresponding to their line item. It won't work with your existing foreach loop, however:

$items = array();
foreach ($invoice['new_item_attributes']['description'] as $key => $val) {
    $items[] = array('description' => $val,
                     'qty' => $invoice['new_item_attributes']['qty'][$key],
                     'amount' => $invoice['new_item_attributes']['amount'][$key],
                     'rowTotal' => $invoice['new_item_attributes']['rowTotal'][$key],
    );
}

will make an array $items of your form submission that you can easily manipulate in the way you were originally expecting.