Array Spread Operator

La Lakshmi Priya Updated 19 Oct 2026
6 min read ·Lesson 132 of 143

What Is the Array Spread Operator?

In simple terms: The spread operator ... copies all elements of one array into another array literal. [...$a, ...$b] creates a new array containing the elements of $a followed by the elements of $b.

Technically: Inside an array literal, ...$expression unpacks an array or any Traversable (such as a generator) at that position. Array unpacking with integer keys was introduced in PHP 7.4; unpacking arrays with string keys is supported since PHP 8.1.

$combined = [...$first, 'extra item', ...$second];

Why It Is Useful

  • Combine lists into a new list in a readable, literal-like way.
  • Add items before, between, or after existing elements without modifying the originals.
  • Merge settings with defaults (PHP 8.1+).
  • Convert generators and iterators into arrays inline.

The same ... operator also unpacks arrays into function arguments (see Variadic Functions); this lesson focuses on its use inside array literals.


Combining Lists

Example

<?php
$fruits = ['Mango', 'Banana'];
$vegetables = ['Carrot', 'Beans'];

$groceries = [...$fruits, ...$vegetables];
$withExtras = ['Rice', ...$fruits, 'Milk'];

print_r($groceries);
echo implode(', ', $withExtras) . "\n";
echo implode(', ', $fruits) . "\n";

Output

Array
(
    [0] => Mango
    [1] => Banana
    [2] => Carrot
    [3] => Beans
)
Rice, Mango, Banana, Milk
Mango, Banana

How It Works

  1. ...$fruits inserts 'Mango' and 'Banana' at that position in the new array.
  2. Several arrays can be spread in one literal, and normal elements can be placed anywhere.
  3. The original arrays are not modified — $fruits is unchanged.

Integer Keys Are Renumbered

When spreading arrays with integer keys, PHP does not keep the original keys. Elements receive new sequential keys:

<?php
$featured = [5 => 'Desk Lamp', 9 => 'Notebook'];
$new = [2 => 'Cushion'];

print_r([...$featured, ...$new]);

Output

Array
(
    [0] => Desk Lamp
    [1] => Notebook
    [2] => Cushion
)

This is exactly what you want for lists: no gaps and no overwritten elements. It also means the spread operator is a convenient way to re-index a list: [...$list] behaves like array_values($list) for lists with integer keys.


String Keys (PHP 8.1+)

Since PHP 8.1, arrays with string keys can be spread too. When the same string key appears more than once, the later value wins:

<?php
$defaults = ['theme' => 'light', 'language' => 'en', 'perPage' => 20];
$userSettings = ['language' => 'ta', 'perPage' => 50];

$settings = [...$defaults, ...$userSettings];

print_r($settings);

Output

Array
(
    [theme] => light
    [language] => ta
    [perPage] => 50
)
  • String keys are preserved.
  • language and perPage from $userSettings overwrite the defaults, but keep the position where they first appeared.
  • This behaves like array_merge($defaults, $userSettings).

Version note: In PHP 7.4 and 8.0, spreading an array with string keys throws an Error ("Cannot unpack array with string keys"). Use array_merge() when supporting those versions.

Mixed Keys

<?php
$base = ['title' => 'Report', 10 => 'first page'];
$extra = ['author' => 'Asha', 20 => 'second page'];

print_r([...$base, ...$extra]);

Output

Array
(
    [title] => Report
    [0] => first page
    [author] => Asha
    [1] => second page
)

String keys are preserved, and integer keys are renumbered, in order of appearance.


Spreading Generators and Iterators

Any Traversable can be spread, which turns lazily produced values into an array:

<?php
function evenNumbers(int $limit): Generator
{
    for ($n = 2; $n <= $limit; $n += 2) {
        yield $n;
    }
}

$numbers = [0, ...evenNumbers(8), 100];

echo implode(', ', $numbers) . "\n";

Output

0, 2, 4, 6, 8, 100

This is a compact alternative to iterator_to_array() when you also want to add other elements. Generators are covered in PHP Generators.

Only Arrays and Traversables

<?php
$maybeList = null;

try {
    $result = [...$maybeList];
} catch (Error $e) {
    echo $e->getMessage() . "\n";
}

$safe = [...($maybeList ?? [])];
var_dump($safe);

Output

Only arrays and Traversables can be unpacked
array(0) {
}

Data from functions or optional input may be null. Default it to an empty array with ?? [] before spreading.


Spread vs array_merge() vs +

[...$a, ...$b]array_merge($a, $b)$a + $b
Integer keysRenumberedRenumberedKept; duplicates from $b ignored
String keys, duplicatesLater value wins (PHP 8.1+)Later value winsFirst value wins
Can add individual elements inlineYesNoNo
Works with generatorsYesNo (arrays only)No
Typical useBuilding lists, combining arraysCombining arrays, settingsFilling in missing defaults

Example: The Difference for Lists

<?php
$a = ['A', 'B'];
$b = ['C', 'D', 'E'];

echo implode(', ', [...$a, ...$b]) . "\n";
echo implode(', ', array_merge($a, $b)) . "\n";
echo implode(', ', $a + $b) . "\n";

Output

A, B, C, D, E
A, B, C, D, E
A, B, E

$a + $b keeps keys 0 and 1 from $a and adds only key 2 ('E') from $b — the union operator is not suitable for combining lists. See Merge Arrays for a full comparison.


Spreading Creates a Shallow Copy

The spread operator copies the elements of an array:

  • Nested arrays are copied as values (arrays are always copied on assignment in PHP), so changing the new array does not affect the original.
  • Objects inside the array are copied as handles, so both arrays refer to the same objects.
<?php
$original = [['qty' => 1], new ArrayObject(['qty' => 1])];
$copy = [...$original];

$copy[0]['qty'] = 5;     // nested array: independent
$copy[1]['qty'] = 5;     // object: shared

echo $original[0]['qty'] . "\n";
echo $original[1]['qty'] . "\n";

Output

1
5

Use clone when objects inside an array must be copied independently.


Practical Example: Building Select Options

<?php
$cities = ['MAA' => 'Chennai', 'BLR' => 'Bengaluru', 'HYD' => 'Hyderabad'];
$selected = 'BLR';

$options = ['' => 'Select a city', ...$cities];

foreach ($options as $code => $label) {
    $isSelected = $code === $selected ? ' selected' : '';
    printf(
        "<option value=\"%s\"%s>%s</option>\n",
        htmlspecialchars($code),
        $isSelected,
        htmlspecialchars($label)
    );
}

Output

<option value="">Select a city</option>
<option value="MAA">Chennai</option>
<option value="BLR" selected>Bengaluru</option>
<option value="HYD">Hyderabad</option>

Step-by-Step Explanation

  1. ['' => 'Select a city', ...$cities] builds a new array with a placeholder option first, followed by all cities. The string keys (city codes) are preserved (PHP 8.1+).
  2. $cities itself is unchanged and can be reused elsewhere — for example, to validate a submitted value with isset($cities[$_POST['city']]).
  3. The loop outputs one <option> per entry, marking the selected city and escaping all values.

Common Mistakes

Expecting Integer Keys to Be Preserved

Effect: IDs used as keys ([101 => 'Asha']) are replaced with 0, 1, ….

Fix: Use + or array_replace() when integer keys carry meaning.

Spreading null or Scalars

Effect: Error: Only arrays and Traversables can be unpacked.

Fix: Default with ?? [].

Spreading String Keys on PHP < 8.1

Effect: Error: Cannot unpack array with string keys.

Fix: Use array_merge() for older PHP versions.

Assuming a Deep Copy

Effect: Objects inside the copied array are shared.

Fix: Clone objects explicitly when independent copies are required.


Best Practices

  • Use [...$a, ...$b] to combine lists and to insert elements inline.
  • Use string-key spreading (PHP 8.1+) for simple "defaults + overrides" merges.
  • Use + or array_replace() when integer keys must be preserved.
  • Guard possibly-null values with ?? [] before spreading.
  • Remember that spreading creates a new array; the originals are never modified.

Official reference: https://www.php.net/manual/en/language.types.array.php#language.types.array.unpacking

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Home PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement PHP Home PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope PHP Casting Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence Continue Statement Modify Strings PHP If...Else...Elseif PHP If Modify Strings PHP If Operators PHP Functions Concatenate Strings PHP If...Else Slicing Strings User-defined Functions Slicing Strings PHP Shorthand if Escape Characters Default Argument Values PHP Nested if Pass by Reference String Interpolation Named Arguments PHP File Upload Variadic Functions Return Values Search in Strings Multibyte Strings Type Declarations in Functions PHP Numbers PHP Math PHP Floats PHP Random Numbers PHP Constants PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Cookies PHP Destructor PHP Access Modifiers Readonly Properties PHP Sessions PHP Inheritance Method Overriding PHP Filters The final Keyword CSRF Protection PHP Filters Advanced Session Security Secure Cookies PHP Magic Constants File Upload Security PHP Callback Functions PHP Operators Filesystem Security PHP JSON Arithmetic Operators Error Reporting in Production Hiding PHP Assignment Operators PHP Configuration (php.ini) Comparison Operators PHP Command Line (CLI) PHP Exceptions Increment / Decrement Operators Migrating to PHP 8 PHP Form Validation PHP Form Required PHP Form URL/E-mail Error Handling Form Input Sanitizing Escaping Output (htmlspecialchars) Custom Error Handler Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators AJAX PHP AJAX Database AJAX XML AJAX Live Search AJAX Poll AJAX with JSON Security Introduction Password Hashing SQL Injection Prevention XSS Prevention Garbage Collection Project: Simple Blog PHP What is OOP PHP Classes/Objects The $this Keyword Access Array Items Update Array Items Add Array Items Remove Array Items Sorting Arrays Multidimensional Arrays Array Destructuring Array Spread Operator Search in Arrays Merge Arrays PHP Abstract Classes PHP Interfaces Polymorphism PHP Traits PHP Static Methods PHP Static Properties Late Static Binding Magic Methods Object Cloning
Ask about this post
AI Ask about this post

Ask questions about Array Spread Operator and get answers drawn from it.

Signed-in readers only.