DEV Community

Cover image for How to Flatten an array in PHP (four methods)
Reza Lavarian
Reza Lavarian

Posted on • Originally published at decodingweb.dev

How to Flatten an array in PHP (four methods)

Update: This post was originally published on my blog decodingweb.dev, where you can read the latest version for a 💯 user experience. ~reza

There’s no built-in function in PHP to flatten a multi-dimensional array, but it’s not a difficult thing to do in PHP. In fact, it’s quite easy.

We usually flatten arrays of data fetched from a database or an API. In real-world scenarios, we’d usually want to take a few fields off each row for displaying in our views.

How to flatten an array in PHP

In this tutorial, we’ll explore four ways of flattening arrays (two-dimensional and multi-dimensional) in PHP:

  1. Flatten two-dimensional arrays in PHP (when keys don’t matter)
  2. Pluck a list of the given key/value pairs from a PHP array
  3. Flatten a PHP array recursively I
  4. Flatten a PHP array recursively II

Flatten two-dimensional arrays in PHP

If you have a two-dimensional array, you can flatten it by unpacking the array and passing it as an argument to the array_merge() function.

<?php

// Each array has two Apple devices in each category (iPads, phones, and laptops)
$products = [
     ['iPad Air', 'iPad pro'],
     ['iPhone 13', 'iPhone 13 mini'],
     ['MacBook Air', 'MacBook Pro']
];

// Flatten the array
$result = array_merge(...$products);
print_r($result);
Enter fullscreen mode Exit fullscreen mode

And this will be the output:

Array
(
  [0] => iPad Air
  [1] => iPad pro
  [2] => iPhone 13
  [3] => iPhone 13 mini
  [4] => MacBook Air
  [5] => MacBook Pro
)
Enter fullscreen mode Exit fullscreen mode

In PHP versions before 8.1, if the $products array has string keys, you must extract the values with array_values() first:

<?php
// ...

$result = array_merge(...array_values($products));
Enter fullscreen mode Exit fullscreen mode

For PHP versions before 7.4: if the $products array is empty, the array_merge() would be invoked without arguments. This will raise an error. To avoid the error, add an empty array [] to the array_merge() arguments:

<?php
// ...

$results = array_merge([], ...$products);
Enter fullscreen mode Exit fullscreen mode

Argument unpacking has been available since PHP 5.6+.

Note: Since PHP 8.1, unpacking the outer array with string keys (associative arrays) is possible without using array_values().

Pluck a list of the given key/value pairs from the array

If you have an array of arrays (two-dimensional), and you want to take a specific key (e.g., name) off each array and create an array of names, you can use array_column().

Imagine you've fetched a list of customers from the database, and you have the results as a two-dimensional array. Now you want to create an array containing the name of each person.

Here's how it's done:

<?php

// Array representing a possible record set returned from a database
$records = array(
    array(
        'id' => 2135,
        'first_name' => 'John',
        'last_name' => 'Doe',
    ),
    array(
        'id' => 3245,
        'first_name' => 'Sally',
        'last_name' => 'Smith',
    ),
    array(
        'id' => 5342,
        'first_name' => 'Jane',
        'last_name' => 'Jones',
    ),
    array(
        'id' => 5623,
        'first_name' => 'Peter',
        'last_name' => 'Doe',
    )
);

$first_names = array_column($records, 'first_name');
print_r($first_names);
Enter fullscreen mode Exit fullscreen mode

And the output will be:

Array
(
    [0] => John
    [1] => Sally
    [2] => Jane
    [3] => Peter
)
Enter fullscreen mode Exit fullscreen mode

Flatten a PHP array recursively I

If your array has more than two dimensions (multi-dimensional), we need to take a recursive approach. The starter method is array_walk_recursive().

Here's how it's done:

<?php

$data = [
    'name' => 'James',
    'contact' => [
        'phone' => [
            'work_phone' => '000',
            'home_phone' => '111'
        ],
        'emails' => 'james@test',
    ]
];

$results = [];
array_walk_recursive($data, function ($item, $key) use (&$results){$results[$key] = $item;});

print_r($results);
Enter fullscreen mode Exit fullscreen mode

This function takes an array and iterates over every element recursively. On each iteration, the provided callback is executed.

The callback accepts two arguments, $item and $key.

Since the $results array is declared in the global scope, we import it into the callback (via use()) as a reference (&$results) - so that we can modify it.

And this will be the output:

Array
(
  [name] => James
  [work_phone] => 000
  [home_phone] => 111
  [emails] => james@test
)
Enter fullscreen mode Exit fullscreen mode

Please note if there are elements with the same key, the former will be overridden by the latter.

Flatten a PHP array recursively II

If you need more control over the flattening process, it's easy to create a recursive function yourself.

Let's see how:

<?php

$data = [
    'name' => 'James',
    'contact' => [
        'phone' => [
            'work_phone' => '000',
            'home_phone' => '111'
        ],
        'emails' => 'james@test',
    ]
];

function flatten($array) {
    $results = [];

    foreach ($array as $key => $value) {
        if (is_array($value) && ! empty($value)) {
            $results = array_merge($results, flatten($value));
        } else {
            $results[$key] = $value;
        }
    }

    return $results;
}


$results = [];
$results = flatten($data);

print_r($results);
Enter fullscreen mode Exit fullscreen mode

In the above code, we took a recursive approach. The flatten() function takes a PHP array and iterates over all the elements by a foreach().

On each iteration, we check if the current value is an array and not empty.

If it's a non-empty array, we call the flatten() function with the current element as its argument.

If the current element isn't an array, we push it to $results.

Basically, the function keeps calling itself until it has gone over all non-array elements (down to the deepest level), and has pushed them to the $results array.

And this will output:

Array
(
  [name] => James
  [work_phone] => 000
  [home_phone] => 111
  [emails] => james@test
)
Enter fullscreen mode Exit fullscreen mode

Wrapping up

We usually flatten arrays fetched from a data source, like a database or an API. Taking a recursive approach is usually the most natural way to flatten arrays. However, array_walk_recursive() and array_column() work quite well in specific scenarios.

I hope you found this guide helpful.

Thanks for reading.


❤️ You might like

Top comments (1)

Collapse
 
web-medias profile image
Web-Medias

Yes reza! It is so cool the recursive method (II) and in other words, it can be used properly to build a full flow of items for a select element with <option> and its <optgroup>...
I ve change a litle bit the way of item is setted in the else case :

Flatten a PHP array recursively II to create a grouped options

<?php

$data = [
    'guid-1' => 'Custom title 1',
    'guid-2' => 'Custom title 2',

    'Posts' => [
        'guid-3' => 'Custom title 3',
        'guid-4' => 'Custom title 4'
    ],
    'Pages' => [
        'guid-5' => 'Custom title 5',
        'guid-6' => 'Custom title 6'
    ],

];


function flatten($array) {
    $results = [];

    foreach ($array as $key => $value) {
        if (is_array($value) && ! empty($value)) {
            $results = array_merge($results, ['<optgroup label="'.$key.'" aria-label="'.$key.'">'], flatten($value), ['</optgroup>'] );
        } else {
            array_push( $results,  '<option value="'.$key.'" label="'. htmlentities($value, ENT_QUOTES) .'">'. $value .'</option>' );
        }
    }

    return $results;
}


$results = [];
$results = flatten($data);

echo "<pre><code>";
print_r($results);
echo "</code></pre>";
Enter fullscreen mode Exit fullscreen mode