I have a somewhat complex nested repeater in WordPress (using ACF), and I am building a frontend form that lets users submit posts.
Let's say I have a repeater field (just an array) Spaces
, and another nested repeater field Walls
.
A user can add spaces (main repeater), which all have multiple walls (nested repeater). In the frontend, the main repeater fields look somewhat like this:
<input type="text" name="spaces[1][space]">
<input type="text" name="spaces[2][space]">
Via AJAX, I add this field to the database in PHP with the following code:
if(isset($_POST['spaces'])) {
$spaces = array();
foreach ($_POST['spaces'] as $value) {
$spaces[] = array(
"space" => $value['space'],
)
}
}
This is working fine. Now the probems starts when I try to nest another array for the different walls a user has added to this space.
The input fields look like this:
<input type="text" name="spaces[1][walls][1][orientation]">
<input type="text" name="spaces[1][walls][2][orientation]">
I know the following PHP code works and correctly puts the right fields in the database:
if(isset($_POST['spaces'])) {
$spaces = array();
foreach ($_POST['spaces'] as $value) {
$spaces[] = array(
"space" => $value['space'],
"walls" => array(
array(
"orientation" => 'North',
),
array(
"orientation" => 'South',
),
)
)
}
}
But of course this is just a static example and I have no idea how to change the above snippet so it takes the correct values through the $_POST variable... Obviously, a user can select more or less than 2 walls, so I need to adjust it for multiple arrays.
For submitting the data via AJAX I'm using a simple call like this:
var formData = form.serialize();
$.ajax({ type: 'POST', url: ajaxurl, data: formData })
Any help would be highly appreciated, as I have been breaking my head over this the past 7 hours.
Update 1: I edited my code like below, which seems to be working (altough it's obivously not the best approach in terms of good practice):
if(isset($_POST['spaces'])) {
$spaces = array();
foreach ($_POST['spaces'] as $value) {
if($value['walls']) {
$walls_array = array();
foreach ($value['walls'] as $wall) {
$walls_array[] = array( "orientation" => $wall['orientation'] );
}
} else {
$walls_array = '';
}
$spaces[] = array(
"space" => $value['space'],
"walls" => $walls_array,
"extra_information" => $value['extra_information'],
);
}
}
Update 2: Based on the answer of @mickmackusa, I was able to edit to edit my code as follows, which works great:
$spaces = array_map(
fn($space) => [
"space" => $space['space'],
"walls" => array_map(
fn($wall) => [
"orientation" => $wall['orientation'],
"comments" => $wall['comments']
], $space['walls']),
"extra_information" => $space['extra_information'],
],
$_POST['spaces'] ?? []
);
Update 3: As users will be able to add and reorder spaces and walls, it's almost impossible to keep the indexes in the HTML input fields. So instead of this:
<input type="text" name="spaces[1][walls][1][orientation]">
<input type="text" name="spaces[1][walls][2][orientation]">
I would like to have it like this:
<input type="text" name="spaces[][walls][][orientation]">
<input type="text" name="spaces[][walls][][orientation]">
In another post on SO, I found this code, which works as long as I don't add any walls to a space. But as soon as I add walls, the fields are incorrectly put into the database with extra empty spaces and walls:
$spaces_temp = [];
foreach($_POST['spaces'] as $k=>$v){
$val = intdiv($k,2);
$spaces_temp[$val][key($v)]=$v[key($v)];
}
$_POST['spaces']=$spaces_temp;