At first glance, this is just a basic HTML form submission problem. In practice, though, it turns into a very useful technique—especially when a form can generate input groups dynamically.

The typical scenario looks like this:

form example

When fields can be added on the fly, fixed name attributes quickly become a problem. If every group uses the same field names, values will overwrite each other or become difficult to distinguish on the server side.

The traditional approach: give every field a unique name

One straightforward way is to manually assign a unique name to every input you plan to submit:

<form id="form1" action="./index.php" method="get">
    <div class="form-control">
        <input type="text" name="name1" />
        <input type="text" name="num1" />
        <input type="text" name="img1" />
    </div>
    <br>
    <div class="form-control">
        <input type="text" name="name2" />
        <input type="text" name="num2" />
        <input type="text" name="img2" />
    </div>
    <br>
    <div class="form-control">
        <input type="text" name="name3" />
        <input type="text" name="num3" />
        <input type="text" name="img3" />
    </div>
    ......
  <input type="submit" value="Submit" />
</form>

The browser sends data in a format like this:

browser submission format

And once the server prints the received values, the structure looks like this:

server output

It works, but it is not friendly for backend processing at all. The data is scattered across unrelated keys, and grouping related values together becomes extra work.

A better option: submit the form as an array

A much cleaner solution is to name fields as nested array keys:

<form id="form1" action="./index.php" method="get">
    <div class="form-control">
        <input type="text" name="infos[1][name]" />
        <input type="text" name="infos[1][num]" />
        <input type="text" name="infos[1][img]" />
    </div>
    <br>
    <div class="form-control">
        <input type="text" name="infos[2][name]" />
        <input type="text" name="infos[2][num]" />
        <input type="text" name="infos[2][img]" />
    </div>
    <br>
    <div class="form-control">
        <input type="text" name="infos[3][name]" />
        <input type="text" name="infos[3][num]" />
        <input type="text" name="infos[3][img]" />
    </div>
    ......
  <input type="submit" value="Submit" />
</form>

The browser submission and backend output now become:

browser submission as array

server array output

If you look closely, the submitted field names are no longer all distinct in the old sense. Instead, they are organized under the same root key and interpreted as an array. Once the data reaches the backend, it is far more structured and much easier to handle.

One small detail matters here: when writing array keys in the name attribute, do not add quotation marks. Otherwise, those quotes become part of the actual key.

What if the number of groups is unknown?

In real projects, the number of submitted groups is often not fixed. Users may add as many rows as they want on the frontend, so manually maintaining indexes like 1, 2, 3 becomes inconvenient.

A practical way to handle that is this:

dynamic form solution

With this pattern, you no longer need to manage the second-level array indexes yourself. The browser will generate them automatically:

browser-generated indexes

And the backend receives a much cleaner structure:

clean backend data

This approach is especially suitable when you need to submit an unknown number of related data groups together. Instead of flattening everything into separate field names, you can preserve the relationship between values from the moment the form is submitted.