9

i'm having some problem with posting data as an array of array. This is how i'd like my data to be POSTED:

array(
['someName'] =>
array([0] =>
      array(['description'] =>890
            ['valore'] =>444)
      [1] =>
      array(['description'] =>98090
            ['value'] =>77)
) 

I know i can achieve this if my html is like this:

<input type='text' name="someName[0][value]">
<input type='text' name="someName[0][description]">
<input type='text' name="someName[1][value]">
<input type='text' name="someName[1][description]">

My problem is that the input fields are on rows of a table and the user can add/remove as many rows as he want, so i can't have fixed index (or i have to modify the name of the input fields each time a row is added since every time i add a row i clone the upper row in the table)

So what i am asking is one of these two things:

1) is there a way to post data the way i want without specifing an index

2)if not, how can i modify dynamically the new input field so that they have an updated name with the new index?

EDIT - i had alredy tried using name="someName[value][]" and name="someName[description][]" but the output is not the desired one:

array(['terreniOneri'] =>
       array(['descrizione'] =>array([0] =>890
                                      [1] => 98090)
               ['valore'] =>array([0] =>444
                                  [1] =>677)
      ) 

i know i can iterate on this array in php i was just wondering if i could avoid it.

3
  • 1
    Commenting since no time for a comprehensive answer: Rather than copying the top row you could generate a template row in a variable (eg var template='<tr><td><input name=someName[%%ROWNUM%%][description]>...</td></tr> and then replace all occurences of %%ROWNUM%% with the next index you want (you'll have to keep track of your count). Then use jquery to build that as HTML and add it in at the end of your table. Commented May 20, 2011 at 13:25
  • @chris i need to clone the row because "someName" may vary depending on the row and so i can't hardcode it. What i should do (but i don't know how to do it) is to change the index in the name (just the number) in the new row (so that if i have someName[1][description] in the orginal row, the copy has someName[2][description]) No problem when subtracting as you pointed out! Commented May 20, 2011 at 13:41
  • Well you can always make "someName" a template variable too or store different templates for different purposes, etc. Once you're playing with javascript you should be able to do whatever you want really. Commented May 20, 2011 at 14:23

2 Answers 2

7

Do it the way you put in the question. If the user removes some row, your form elements would be:

<form action="..." method="post" onsubmit="return reindexer(this);">
    <input type='text' name="someName[0][value]">
    <input type='text' name="someName[0][description]">
    <input type='text' name="someName[2][value]">
    <input type='text' name="someName[2][description]">
</form>

But there's no problem to traverse an array with non-contiguous numeric indexes in php: use a foreach loop.

<?php
if (count($_POST['somename']) > 0)
{
    foreach ($_POST['somename'] as $row)
    {
        echo "Value: ".$row['value']."<br />\n";
        echo "Description: ".$row['description']."<br />\n";
    }
}

If you need to know the number of each row as a continous index (in the example provided, row 0 would still be 0, but row 2 should be 1 (as the user deleted one row), you can use a variable acting as a counter:

<?php
if (count($_POST['somename']) > 0)
{
    $i = 0;
    foreach ($_POST['somename'] as $row)
    {
        echo "Index $i<br />\n";
        echo "Value: ".$row['value']."<br />\n";
        echo "Description: ".$row['description']."<br />\n";
        $i++;
    }
}

I think this approach has more sense that the other solutions, as this way you would have an array of items, being each item a value and a description, instead of having two separate arrays of values and descriptions and having to get the values for your item from those two arrays instead of one.

edit: I've modified the first piece of code to include the <form> element. This would be the accompanying js function:

<script type="text/javascript">
function reindexer(frm)
{
    var counter = 0;
    var inputsPerRow = 2;
    for (var idx = 0; idx < frm.elements.length; idx++)
    {
        elm.name = elm.name.replace('%%INDEX%%', counter);
        if (idx % inputsPerRow == 1)
        {
            // only increment the counter (or row number) after you've processed all the
            // inputs from each row
            counter++;
        }
    }
}
</script>
Sign up to request clarification or add additional context in comments.

9 Comments

the problem is when the user add a row (that's because i clone the upper row): in this case the new row would have the same name as the old one and would overwrite it when posted
When you add a row, it gets appended at the end of the table, or between two existing rows?
between existing rows. And i have to clone it because 'somename' changes between rows of the table
Then I would go with something like Chris' comment in the question. At the beginning, before the user clones any row, all your rows have the string "%%INDEX%%" as index (name="somename[%%INDEX%%][value]). You capture the onsubmit event of the form, and then for each input you have in the form, replace %%INDEX%% with a counter. Downside from this approach is that if some user has js disabled (we exist) your code would only process the last row (as each row would overwrite the previous (all would have the same index).
@Carlos: surely the downside would just be an inability to add new rows? If the js doesn't work for renaming the indexes then it won't work for adding new rows.
|
4

Try like this:

<input type='text' name="someNameValue[]">
<input type='text' name="someNameDescription[]">

If the fields are paired, they can be attached by the indexes. So if you have the 10th row, someNameValue[9] and someNameDescription[9] will be a pair. You can merge them.

EDIT: You don't have to write the indexes manually, they will be automatically generated.

<input type='text' name="someName[]">
<input type='text' name="someName[]">
<input type='text' name="someName[]">

and

<input type='text' name="someName[0]">
<input type='text' name="someName[1]">
<input type='text' name="someName[2]">

will give the same result in your post array.

6 Comments

I would do it the same way except using someName['value'][] and someName['description'][]. You can then turn that into the array you want via a few rows of php.
Does the HTML spec actually guarantee that the elements POSTed will be posted in a well defined order (such as position in HTML)? Although this would probably work it feels a bit wrong relying on that (though I might be wrong and it is well defined what order they are passed in).
Hmm... I think yes. I used this many times before and never had any problems with it.
if i do someNameValue[] and someNameDexcription[] obviously i have two different arrays and that is not what i want. If i do someName['value'][] and someName['description'][] it's something i tried but it doesn't give what i desire (i'll post above the output)
Then the best option would to generate the index with JS based on the row number.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.