Reputation: 1277
I have one dynamic multidimensional-array having unknown depth. I wanted to replace a key=>value
based on another key=>value
condition.
E.g replace $settings[$cient_id]
's value when $form_id
is 1f44537
.
$data = array (
0 =>
array (
'id' => '2cd5985',
'elType' => 'section',
'settings' => array(),
'elements' => array (
0 => array (
'id' => '88063e6',
'elType' => 'column',
'settings' => array(),
'elements' => array (
0 =>
array (
'id' => '1f44537',
'elType' => 'widget',
'settings' => array (
'ap_google_sheet_client_id' => 'test_id',
),
'elements' => array (
),
'widgetType' => 'form',
),
)
),
1 => array (
'id' => '7878c73',
'elType' => 'column',
'settings' => array(),
'elements' => array (
0 =>
array (
'id' => '1f44537',
'elType' => 'widget',
'settings' => array (
'ap_google_sheet_client_id' => 'test_id',
),
'elements' => array (
),
'widgetType' => 'form',
),
)
),
),
),
);
Here are my unsuccessful tries
Try-1
public function replace_recursive( $elements, $form_id ) {
foreach ( $elements as &$element) {
if ( $element['id'] === $form_id ) {
$element['settings']['ap_google_sheet_client_id'] = 'replaced';
return $elements;
}
if ( ! empty( $element['elements'] ) ) {
$elements = self::replace_recursive( $element['elements'], $form_id );
if ( $elements ) {
return $elements;
}
}
}
}
Try-2
This solved the issue. But the loop doesn't stop when found the element. It loops through all the elements.
public function replace_recursive( $elements, $form_id ) {
foreach ( $elements as &$element) {
if ( $element['id'] === $form_id ){
$element['settings']['ap_google_sheet_client_id'] = 'replaced';
write_log('A');
break;
}
if ( ! empty( $element['elements'] ) ) {
self::replace_recursive( $element['elements'], $form_id );
write_log('B');
}
}
return $elements;
}
Value replaced but I am not getting the full array $elements. Rather than getting the child array for which the value was replaced.
Try-3
Facing the same issue again. The named keys that are on top of elType=widget
are converted to numbered keys. Here is a sandbox.
https://sandbox.onlinephpfunctions.com/code/530fb53612dd7a2017b236f218665c0142f1e63f
Upvotes: 0
Views: 173
Reputation: 350300
As you state, the code is replacing the value correctly. It is just that you are currently returning the value $elements
as it is returned from the recursive call. But that is a smaller array than the overall array, so you should not bubble that array further up.
Instead, just inject that result in the current wrapping array at the "elements" key, and return the resulting array:
$data = [[
'id' => '2cd5985',
'elements' => [[
'id' => '88063e6',
'elements' => [[
'id' => '1f44537',
'settings' => [
'form_name' => 'New Form',
'form_fields' => [[
'custom_id' => 'name',
'field_label' => 'Name',
'placeholder' => 'Name',
'_id' => '948d900',
'field_pattern_message' => 'Please match the requested format',
],
[
'custom_id' => 'email',
'field_type' => 'email',
'required' => 'true',
'field_label' => 'Email',
'placeholder' => 'Email',
'_id' => '243a095',
'field_pattern_message' => 'Please match the requested format',
]],
'ap_google_sheet_client_id' => '',
],
'elements' => [],
'widgetType' => 'form',
]],
'isInner' => false,
]],
'isInner' => false,
]];
function replace_recursive( $elements, $form_id ) {
foreach ( $elements as &$element) {
if ( $element['id'] === $form_id ) {
$element['settings']['ap_google_sheet_client_id'] = 'replaced';
return $elements;
}
if ( ! empty( $element['elements'] ) ) {
$subelements = replace_recursive( $element['elements'], $form_id );
if ( $subelements ) {
// Inject result back into our array
$element["elements"] = $subelements;
return $elements;
}
}
}
}
$res = replace_recursive( $data, "1f44537");
var_dump($res);
See it with another input example in this sandbox
In the second try, you place the return
outside of the loop. But this means you always return the array. Yet, you need somehow an indication whether the replacement happened or not. It is probably better to return null
when you didn't replace the value, and only return the full array when there was a replacement. Otherwise you have no indication when you can stop looking further.
Upvotes: 1