Submitting a multidimensional array via POST with php
Asked Answered
U

5

116

I have a php form that has a known number of columns (ex. top diameter, bottom diameter, fabric, colour, quantity), but has an unknown number of rows, as users can add rows as they need.

I've discovered how to take each of the fields(columns) and place them into an array of their own.

<input name="topdiameter['+current+']" type="text" id="topdiameter'+current+'" size="5" />
<input name="bottomdiameter['+current+']" type="text" id="bottomdiameter'+current+'" size="5" />

So what I end up with in the HTML is:

<tr>
  <td><input name="topdiameter[0]" type="text" id="topdiameter0" size="5" /></td>
  <td><input name="bottomdiameter[0]" type="text" id="bottomdiameter0" size="5" /></td>
</tr>
<tr>
  <td><input name="topdiameter[1]" type="text" id="topdiameter1" size="5" /></td>
  <td><input name="bottomdiameter[1]" type="text" id="bottomdiameter1" size="5" /></td>
</tr>

...and so on.

What I would like to do now is take all the rows and columns put them into a multidimensional array and email the contents of that to the client (preferably in a nicely formatted table). I haven't been able to really comprehend how to combine all those inputs and selects into a nice array.

At this point, I'm going to have to try to use several 1D arrays, although I have the idea that using a single 2D array would be a better practice than using several 1D arrays.

Uticas answered 12/3, 2010 at 15:26 Comment(0)
S
167

On submitting, you would get an array as if created like this:

$_POST['topdiameter'] = array( 'first value', 'second value' );
$_POST['bottomdiameter'] = array( 'first value', 'second value' );

However, I would suggest changing your form names to this format instead:

name="diameters[0][top]"
name="diameters[0][bottom]"
name="diameters[1][top]"
name="diameters[1][bottom]"
...

Using that format, it's much easier to loop through the values.

if ( isset( $_POST['diameters'] ) )
{
    echo '<table>';
    foreach ( $_POST['diameters'] as $diam )
    {
        // here you have access to $diam['top'] and $diam['bottom']
        echo '<tr>';
        echo '  <td>', $diam['top'], '</td>';
        echo '  <td>', $diam['bottom'], '</td>';
        echo '</tr>';
    }
    echo '</table>';
}
Sladen answered 12/3, 2010 at 15:44 Comment(4)
Thanks! I'd started getting close to this, although I had the column and rows flipped.Uticas
How about if you are cloning text fields and have no control in adding names for list such as name="diameters[0][top] what can I do if I have more than one name? such as top, bottom, left and right? @SladenLeban
@JMASTERB Late addition but you would have to add some processing with JS, i.e if they are in order, you would read the previous input name after cloning, and increment by 1 manually for each input name attribute in the clone.Dinnage
@disgruntledGoat I don't suppose you could do a jsfiddle of this?Grief
J
24

you could submit all parameters with such naming:

params[0][topdiameter]
params[0][bottomdiameter]
params[1][topdiameter]
params[1][bottomdiameter]

then later you do something like this:

foreach ($_REQUEST['params'] as $item) {
    echo $item['topdiameter'];
    echo $item['bottomdiameter'];
}
Jovia answered 12/3, 2010 at 15:38 Comment(0)
I
4

I know this is necro-posting, but I have been running to this same issue and ending up to this same answer many, many, many times, over some years.

Today though I had an additional issue, I wanted my users to be able to add as many items as they want, as well as rearrange their input before submitting, so I came up with this relatively clean solution:

$diameters = [];
foreach($_POST['diameters'] as $k=>$v){
 $val = intdiv($k,2);
 $diameters[$val][key($v)]=$v[key($v)];
}
$_POST['diameters']=$diameters;

The hard coded 2 is because that is the size of the input block (topdiameter, bottomdiameter)

So the html can simply look like this:

<tr>
  <td><input name="diameters[][top]" type="text" [..] /></td>
  <td><input name="diameters[][bottom]" type="text" [..] /></td>
</tr>
<tr>
  <td><input name="diameters[][top]" type="text" [..] /></td>
  <td><input name="diameters[][bottom]" type="text" [..] /></td>
</tr>

This way you will end up having a simple array in the format of:

$_POST['diameters']=[
  ["top"=>"","bottom"=>""],
  ["top"=>"","bottom"=>""],
  ...
]

Which should make whatever you need to do with your data much simpler.

Injured answered 22/5, 2021 at 19:9 Comment(3)
The diameters[] without indexes(numbers) works great on dynamic lists which can have deleted rows. And the foreach is a great tool to make nice ordered arrays. For newbies note the intdiv() is meant for 2 subelements in each main element in the array. For more, like [top],[bottom],[right],[left] you would need to divide by 4.Beauty
@Injured , your code has been very helpful in my own project, where users also have the option to add rows and reorder them. However, it's a bit more complex, as within each row there are again more rows. For example: name="spaces[][walls][][orientation]". How would I edit your code for this to work? Many thanks!Underwent
@SenneVandenputte I'm not entirely sure what or how you would like to have them reorder and how to group them, but if I were you, and because it looks like you are having quite a bit of complexity in the front end, I would add a front end js framework, at least smthng minimal like alpinejs or even jQuery to handle the data with that before submitting it through js.Injured
G
1

@DisgruntledGoat 's answer is absolutely correct; however, in case anyone is looking for values that are not set to required, meaning $_POST === null could happen, you would use the isset() conditional as such:

$placeHolderValue = "Incomplete";

if ( isset( $_POST['diameters'] ) )
{
    echo '<table>';
    foreach ( $_POST['diameters'] as $diam )
    {
        // here you have access to $diam['top'] and $diam['bottom']
        echo '<tr>';
        if (isset($diam['top'])) {
            echo '  <td>' . $diam['top'] . '</td>';
        } else {
            echo '<td>' . $placeHolderValue . '</td>';
        if (isset($diam['top'])) {
            echo '  <td>' . $diam['bottom'] . '</td>';
        } else {
            echo '<td>' . $placeHolderValue . '</td>';
        echo '</tr>';
    }
    echo '</table>';
}

This all using the naming format that @DisgruntledGoat mentioned in their answer.

Grief answered 19/4, 2022 at 17:50 Comment(0)
V
0

I made a function which handles arrays as well as single GET or POST values

function subVal($varName, $default=NULL,$isArray=FALSE ){ // $isArray toggles between (multi)array or single mode

    $retVal = "";
    $retArray = array();

    if($isArray) {
        if(isset($_POST[$varName])) {
            foreach ( $_POST[$varName] as $var ) {  // multidimensional POST array elements
                $retArray[]=$var;
            }
        }
        $retVal=$retArray;
    }

    elseif (isset($_POST[$varName]) )  {  // simple POST array element
        $retVal = $_POST[$varName];
    }

    else {
        if (isset($_GET[$varName]) ) {
            $retVal = $_GET[$varName];    // simple GET array element
        }
        else {
            $retVal = $default;
        }
    }

    return $retVal;

}

Examples:

$curr_topdiameter = subVal("topdiameter","",TRUE)[3];
$user_name = subVal("user_name","");
Varietal answered 6/11, 2018 at 13:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.