Collection::flatten
Flattens a multi-dimensional collection into a single dimension, to an optional depth.
Collection::flatten(int|float $depth = INF): staticParameters
| Parameter | Type | Description |
|---|---|---|
$depthoptional | int|float= INF | How many levels of nesting to unwrap. The default INF flattens all the way down; 1 unwraps a single level and leaves anything below it intact. |
Return value
staticA new, re-indexed collection containing the values found at or below the requested depth. Keys are never preserved — the result is always a list starting at 0.
flatten walks a collection and pulls every nested array or collection up into a single dimension. With no argument it recurses all the way to the leaves; with a numeric depth it stops after that many levels.
When to reach for it
The classic case is a pluck that returned arrays — a list of tag arrays, a list of role arrays — which you want as one flat list before unique or implode. It also cleans up the output of groupBy when you decide you only wanted the rows after all. Nested Collection instances are unwrapped alongside plain arrays, so you do not have to normalise first.
The thing that trips people up
Keys are discarded — always, at every level, whether they were strings or integers. The result is a freshly indexed list. That is the point when you are flattening a list of lists, but it destroys the structure of an associative array: flattening ['name' => 'Taylor', 'languages' => [...]] leaves you with the values only, and no way to tell which was which.
The other surprise is the default depth. INF means a deeply nested payload is torn all the way down to its scalars, so rows of data become a stream of unlabelled fields. When you only wanted to merge the outer level, pass 1 explicitly.
Example
When to use it
- Turn a plucked list of tag arrays into one flat list before calling unique().
- Merge the grouped rows produced by groupBy back into a single collection.
- Collapse a two-level API response into one list of records with flatten(1).
Frequently asked questions
Does flatten preserve the collection's keys?
No. flatten always discards keys and returns a re-indexed list starting at 0, at every depth. Chaining values() afterwards is harmless but redundant.
How do I flatten only one level?
Pass 1 as the depth: flatten(1). The default depth is INF, which recurses all the way down to the scalar leaves and destroys any record structure.
What is the difference between flatten and flatMap?
flatten only unwraps existing nesting, while flatMap runs a callback over each item first and then collapses the results by exactly one level. Use flatMap when you need to transform and expand in the same pass.
More examples
Nested collections are unwrapped too
The first output is the flat list Ada, Grace, Linus — flatten treats a nested Collection exactly like a nested array, so mixed structures need no normalising. The second shows the most common real use: pluck returns a collection of role arrays, flatten merges them, and unique reduces the result to admin and billing.
<?php
$teams = collect([
collect(['Ada', 'Grace']),
collect(['Linus']),
]);
print_r($teams->flatten()->all());
$roles = collect([
['name' => 'Ada', 'roles' => ['admin', 'billing']],
['name' => 'Linus', 'roles' => ['admin']],
]);
print_r($roles->pluck('roles')->flatten()->unique()->values()->all());Depth is the difference between data and confetti
flatten(1) yields three record arrays, so pluck('title') can still read a field and prints First, Second, Third. The unbounded call yields 1, First, 2, Second, 3, Third — the ids and titles interleaved with nothing marking which is which. This is the single most common flatten bug report.
<?php
$response = collect([
'page_1' => [
['id' => 1, 'title' => 'First'],
['id' => 2, 'title' => 'Second'],
],
'page_2' => [
['id' => 3, 'title' => 'Third'],
],
]);
// Right: three records.
print_r($response->flatten(1)->pluck('title')->all());
// Wrong: six unlabelled scalars.
print_r($response->flatten()->all());Flattening after groupBy
The first line prints red, blue. The second prints Ada, Cleo, Bob — flatten(1) merges the groups back into one collection, but in group order rather than the original row order. That reordering is worth remembering if you flatten a grouped collection and then rely on the sequence.
<?php
$rows = collect([
['team' => 'red', 'name' => 'Ada'],
['team' => 'blue', 'name' => 'Bob'],
['team' => 'red', 'name' => 'Cleo'],
]);
$grouped = $rows->groupBy('team');
echo $grouped->keys()->implode(', '), PHP_EOL;
echo $grouped->flatten(1)->pluck('name')->implode(', '), PHP_EOL;
Discussion