1

I have two arrays, that I want to merge as one according to keys suffix.

$keys = array(
  'staff_first_name' => NULL,
  'staff_last_name' => NULL,
  'staff_years' => NULL
);


$submitted_values = array( 
   'first_name' => 'jon',
   'last_name' => 'doe',
   'years' => 5
);

I understand I could use a function like shown here and modify it.

But is there a native php function that will accomplish this. I attempted to use array_merge_recursive but after reviewing the documentation It will not do what I need it to.

$wanted_array = array(
   'staff_first_name' => 'jon',
   'staff_last_name' => 'doe',
   'staff_years' => 5
);
Andreas
  • 23,610
  • 6
  • 30
  • 62
Orlando P.
  • 621
  • 3
  • 19
  • I don't think you should blindly replace array elements with user-supplied data without specifying the exact key relationship. If this was my project, I'd sync the keys for the sake of merging and just call array_replace. Is `$submitted_values` actually a `$_GET`? – mickmackusa May 18 '18 at 20:48
  • If it is GET or POST it should be quite easy to fix the associative name. Much better than doing coding backed to match it. – Andreas May 18 '18 at 20:54
  • @mickmackusa submitted values is a sanitized $_POST. $keys array doesn't actually hold data just the keys are the fields I am looking for in the $_POST array. – Orlando P. May 18 '18 at 20:55
  • So your looking for them also? That means you need to filter them out from the submitted values before combining? – Andreas May 18 '18 at 21:10
  • @OrlandoP see my updated answer – Andreas May 18 '18 at 21:33

4 Answers4

4

If you know the two arrays are the same size, and in the same order, you can use array_combine with array_keys.

$wanted_array = array_combine(array_keys($keys), $submitted_values);
Don't Panic
  • 41,125
  • 10
  • 61
  • 80
3

Because it's a suffix that is the same on each key we don't need to worry about it.
If we ksort the arrays they should both be sorted the same because the suffix is the same on all in key array.

$keys = array(
   'staff_first_name' => NULL,
   'staff_last_name' => NULL,
   'staff_years' => NULL
);


$values = array( 
    'years' => 5,
    'first_name' => 'jon',
    'last_name' => 'doe',
);

ksort($values);
ksort($keys);
Var_dump(array_combine(array_keys($keys), $values));

I intentionally placed years first to show that it works.
https://3v4l.org/cBNhk


If you need to reduce the $_POST to only these array items to be able to combine them you can use a combination of preg_grep, array_flip, array_values and array_intersect_key to filter out the wanted items from the array.

$val = preg_grep("/first_name|last_name|years/",array_values(array_flip($values)));

$values = Array_intersect_key($values, array_flip($val));
ksort($values);
ksort($keys);
Var_dump(array_combine(array_keys($keys), $values));

I added some extra items to simulate a larger mixed $_POST array.
https://3v4l.org/a3ju1

Andreas
  • 23,610
  • 6
  • 30
  • 62
1

This is one of those questions where I must implore the OP to rethink their process. It only complicates your code to introduce associative keys that do not instantly synchronize with your form field names. This is the best advice that I can give you: declare a whitelist of keys and assign default values to each, then filter, then replace.

Since your values are all null, your code can be made more DRY by calling array_fill_keys().

The following can be written as one line of code, but to show each step, I've printed the arrays to screen after each function call.

Code: (Demo)

$defaults = array_fill_keys(['first_name', 'last_name', 'years'], null);
var_export($defaults);

$_GET = [
         'last_name' => 'doe',
         'Hackers' => 'can be naughty',
         'years' => 5
        ];
var_export($_GET);

$screened = array_intersect_key($_GET, $defaults);
var_export($screened);

$replaced = array_replace($defaults, $screened);
var_export($replaced);

Output:

array (
  'first_name' => NULL,
  'last_name' => NULL,
  'years' => NULL,
)array (
  'last_name' => 'doe',
  'Hackers' => 'can be naughty',
  'years' => 5,
)array (
  'last_name' => 'doe',
  'years' => 5,
)array (
  'first_name' => NULL,
  'last_name' => 'doe',
  'years' => 5,
)

...p.s. makes sure that you use prepared statements with placeholders if you are sending any of the values to the database.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • @Orlando Whoops I should have used $_POST. The process logic remains the same. – mickmackusa May 19 '18 at 04:39
  • Thanks for the input yes this makes more sense. Due to the form and supporting different type of submissions I started going down the hacky way but I will instead just use different forms and follow this pattern. Thank You – Orlando P. May 21 '18 at 15:25
0

Using array_combine() is liable to suffer breakage if the volume of data is inconsistent or the order of the elements.

For more reliability, you can use a key map to act as an adaptor between the two arrays.

If the sought value at the targeted element doesn't exist, then the initial null value will be retained.

Code: (Demo)

$keyMap = [
   'staff_first_name' => 'first_name',
   'staff_last_name' => 'last_name',
   'staff_years' => 'years'
];

foreach ($keys as $key => &$value) {
    $value = $submitted_values[$keyMap[$key] ?? ''] ?? $value;
}
var_export($keys);

Without a key map, you can simply trim the prefix from the key to access the submitted elements. Demo

foreach ($keys as $key => &$value) {
    $value = $submitted_values[substr($key, 6)] ?? $value;
}
var_export($keys);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136