68

I got a form like this

<form>
    <input type="text" class="form-control" placeholder="Titel" name="levels[level]">
    <input type="text" class="form-control" placeholder="Titel" name="levels[build_time]">

    <input type="text" class="form-control" placeholder="Titel" name="levels[level]">
    <input type="text" class="form-control" placeholder="Titel" name="levels[build_time]">
</form>

I'd like to have as $_POST output an array like:

Array (
  [1] => Array ( [level] => 1 [build_time] => 123 )
  [2] => Array ( [level] => 2 [build_time] => 456 )
)

I know I could do something like name="levels[1][build_time]" and so on, but since these elements get added dynamically, it would be hard to add an index. Is there another way?


As suggested, I changed my form. I also included my whole HTML now, because I think I'm missing something here. My HTML now:

<div class="form-group">
  <label class="col-md-2">Name(z.B. 1)</label>
  <div class="col-md-10">
    <input type="text" class="form-control" placeholder="Titel" name="levels[][level]">
  </div>

  <label class="col-md-2">Bauzeit(In Sekunden)</label>
  <div class="col-md-10">
    <input type="text" class="form-control" placeholder="Titel" name="levels[][build_time]">
  </div>
</div>

<div class="form-group">
  <label class="col-md-2">Name(z.B. 1)</label>
  <div class="col-md-10">
    <input type="text" class="form-control" placeholder="Titel" name="levels[][level]">
  </div>

  <label class="col-md-2">Bauzeit(In Sekunden)</label>
  <div class="col-md-10">
    <input type="text" class="form-control" placeholder="Titel" name="levels[][build_time]">
  </div>
</div>

The output I get now is:

[levels] => Array (
  [0] => Array ( [level] => 1 )
  [1] => Array ( [build_time] => 234 )
  [2] => Array ( [level] => 2 )
  [3] => Array ( [build_time] => 456 )
)

As suggested in your edit, I edited my form and moved the square brackets to the end of the name. The output I get now is:

[levels] => Array (
  [level] => Array (
    [0] => 1
    [1] => 2
  )
  [build_time] => Array (
    [0] => 234
    [1] => 456
  )
)

I guess that would kind of work, but it still looks complicated. Isn’t there a better way?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Evo_x
  • 2,997
  • 5
  • 24
  • 40

4 Answers4

99

Simply add [] to those names like

 <input type="text" class="form-control" placeholder="Titel" name="levels[level][]">
 <input type="text" class="form-control" placeholder="Titel" name="levels[build_time][]">

Take that template and then you can add those even using a loop.

Then you can add those dynamically as much as you want, without having to provide an index. PHP will pick them up just like your expected scenario example.

Edit

Sorry I had braces in the wrong place, which would make every new value as a new array element. Use the updated code now and this will give you the following array structure

levels > level (Array)
levels > build_time (Array)

Same index on both sub arrays will give you your pair. For example

echo $levels["level"][5];
echo $levels["build_time"][5];
Hanky Panky
  • 46,730
  • 8
  • 72
  • 95
  • Ooops sorry I had my Square brackets at the wrong place. Please move them to end of the name like my new edit. – Hanky Panky Nov 25 '13 at 04:30
  • I see you edited your post again :) I got the same structure now but it's still not what I originally wanted. That's the best way to do it? – Evo_x Nov 25 '13 at 04:35
  • That isn't complicated. You can access one pair like `echo $levels["level"][5]; echo $levels["build_time"][5];` – Hanky Panky Nov 25 '13 at 04:37
  • this is a pretty great feature of HTML, saves a lot of tampering around on server side. Thanks for your answer, it helped me alot – a7omiton Jul 12 '14 at 18:17
38

If it is OK for you to index the array, you can do this:

<form>
    <input type="text" class="form-control" placeholder="Titel" name="levels[0][level]">
    <input type="text" class="form-control" placeholder="Titel" name="levels[0][build_time]">

    <input type="text" class="form-control" placeholder="Titel" name="levels[1][level]">
    <input type="text" class="form-control" placeholder="Titel" name="levels[1][build_time]">

    <input type="text" class="form-control" placeholder="Titel" name="levels[2][level]">
    <input type="text" class="form-control" placeholder="Titel" name="levels[2][build_time]">
</form>

... to achieve this:

[levels] => Array (
  [0] => Array (
    [level] => 1
    [build_time] => 2
  )
  [1] => Array (
    [level] => 234
   [build_time] => 456
  )
  [2] => Array (
    [level] => 111
    [build_time] => 222
  )
)

But if you remove one pair of inputs (dynamically, I suppose) from the middle of the form then you'll get holes in your array, unless you update the input names...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • I would prefer this style of inputs as it becomes easier to process this once posted. However, it's a bit complex when you dynamically add more rows of inputs to the form. Is there any easier solution to this? – Debiprasad Jan 31 '23 at 07:22
20

HTML: Use names as

<input name="levels[level][]">
<input name="levels[build_time][]">

PHP:

$array = filter_input_array(INPUT_POST);
$newArray = array();
foreach (array_keys($array) as $fieldKey) {
    foreach ($array[$fieldKey] as $key=>$value) {
        $newArray[$key][$fieldKey] = $value;
    }
}  

$newArray will hold data as you want

Array ( 
  [0] => Array ( [level] => 1 [build_time] => 123 ) 
  [1] => Array ( [level] => 2 [build_time] => 456 )
)
user6542662
  • 221
  • 2
  • 2
7

In addition:

For those who have a empty $_POST variable, don't use this:

name="[levels][level][]"

Rather use this (as it is already here in this example):

name="levels[level][]"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mheg
  • 111
  • 1
  • 4