Simple Approach for Original Question (Single Dimension)
function flattenParentKey($array, $parentKey)
{
foreach ($array[$parentKey] as $key => $value)
{
$array[$parentKey . '_' . $key] = $value;
}
unset($array[$parentKey]);
return $array;
}
Here's an example in the PHP Shell (php -a
):
php > $user = [
php > 'id' => 1,
php > 'name' => 'Example',
php > 'profile' => [
php > 'last_login' => '10-10-1900',
php > 'another_field' => 'with some data',
php > 'actions' => [
php > 0 => 'Logged in',
php > 1 => 'Logged out',
php > 2 => 'Signed up for news letter'
php > ]
php > ]
php > ];
php > $user = flattenParentArray($user, 'profile');
php > var_dump($user);
array(5) {
["id"]=>
int(1)
["name"]=>
string(7) "Example"
["profile_last_login"]=>
string(10) "10-10-1900"
["profile_another_field"]=>
string(14) "with some data"
["profile_actions"]=>
array(3) {
[0]=>
string(9) "Logged in"
[1]=>
string(10) "Logged out"
[2]=>
string(25) "Signed up for news letter"
}
}
php >
Recursive Approach for Multi-Dimensional Arrays
As you asked in the comments, and I added to your original question, here's how we'd do this with a nested, multi-dimensional array:
$user = [
'id' => 1,
'name' => 'Example',
'profile' => [
'last_login' => '10-10-1900',
'another_field' => 'with some data',
'actions' => [
0 => 'Logged in',
1 => 'Logged out',
2 => 'Signed up for news letter'
],
'friends' => [
'friend_one' => [
'name' => 'Test User',
'email' => 'test@example.com'
],
'friend_two' => [
'name' => 'Test User',
'email' => 'test@example.com'
]
]
]
];
/* Returns true if the specified parameter is an array, is not empty, and is
* not a contiguous numeric array).
*/
function isAssociativeArray($array)
{
if (empty($array) || !is_array($array))
{
return false;
}
/* Returns true if arrays keys are not numeric or contiguous. */
return (bool) array_keys($array) !== range(0, count($array) - 1);
}
/* $parentKey will always be null when we first call this function. As
* it recurses through levels of depth, $parentKey will be passed and
* appended to.
*/
function flattenChildArrays($array, $parentKey = null)
{
$outputArray = [];
foreach ($array as $key => $value)
{
/* If we have a $parentKey, our new key will be "$parentKey_$key" */
$newKey = (($parentKey) ? $parentKey . '_' . $key : $key);
if (isAssociativeArray($value))
{
/* If our $value is an associative array, we'll want to recursively
* call ourselves again on $value with our new key as the $parentKey.
*/
$outputArray = array_merge($outputArray, flattenChildArrays($value, $newKey));
}
else
{
/* If $value is not an associative array (i.e. just a simple value, or a
* contiguous numeric array, just use the value as it is in our output
* array. If we have a parent key (because we're inside 1 or more levels
* of recursion), use "$parentKey_$key" (see where we define $newKey above).
*/
$outputArray[$newKey] = $value;
}
}
return $outputArray;
}
And an example in the PHP shell:
php > $user = [
php > 'id' => 1,
php > 'name' => 'Example',
php > 'profile' => [
php > 'last_login' => '10-10-1900',
php > 'another_field' => 'with some data',
php > 'actions' => [
php > 0 => 'Logged in',
php > 1 => 'Logged out',
php > 2 => 'Signed up for news letter'
php > ],
php > 'friends' => [
php > 'friend_one' => [
php > 'name' => 'Test User',
php > 'email' => 'test@example.com'
php > ],
php > 'friend_two' => [
php > 'name' => 'Test User',
php > 'email' => 'test@example.com'
php > ]
php > ]
php > ]
php > ];
php > var_dump(flattenChildArrays($user));
array(11) {
["id"]=>
int(1)
["name"]=>
string(7) "Example"
["profile_last_login"]=>
string(10) "10-10-1900"
["profile_another_field"]=>
string(14) "with some data"
["profile_actions_0"]=>
string(9) "Logged in"
["profile_actions_1"]=>
string(10) "Logged out"
["profile_actions_2"]=>
string(25) "Signed up for news letter"
["profile_friends_friend_one_name"]=>
string(9) "Test User"
["profile_friends_friend_one_email"]=>
string(16) "test@example.com"
["profile_friends_friend_two_name"]=>
string(9) "Test User"
["profile_friends_friend_two_email"]=>
string(16) "test@example.com"
}
php >
Recursion can be a difficult topic to understand, as it requires you to follow the program through multiple levels in your head, and it can be easy to lose track of where you are. I recommend taking a simple example, and "stepping through" your recursive function, line by line, commenting what each of the values will be on each level of depth.
The answers to this question provide more information about understanding recursion.