ZetCode

PHP Splat Operator

last modified May 21, 2025

In this article, we explore PHP's splat operator (...), also known as the spread operator. Introduced in PHP 5.6, this operator provides two main functionalities: capturing variable-length argument lists in functions (argument unpacking) and unpacking arrays into individual elements.

The splat operator simplifies working with variable numbers of arguments and makes array manipulation more expressive. It's particularly useful for creating flexible APIs and combining arrays.

The advantages of PHP's splat operator are:

By using the splat operator, developers can write more flexible and expressive functions while maintaining clean, readable code.

Basic variadic functions

The splat operator allows functions to accept a variable number of arguments by prefixing a parameter with .... These arguments are then available as an array within the function.

basic_variadic.php
<?php

declare(strict_types=1);

// Simple variadic function
function sumAll(...$numbers): float {
    return array_sum($numbers);
}

echo sumAll(1, 2, 3) . "\n";
echo sumAll(1.5, 2.5, 3.5, 4.5) . "\n";

// With type hints (PHP 7.0+)
function concatenate(string ...$strings): string {
    return implode(' ', $strings);
}

echo concatenate('Hello', 'there', 'from', 'PHP') . "\n";

// Mixing regular and variadic parameters
function createPerson(string $name, int $age, ...$extraInfo): array {
    return [
        'name' => $name,
        'age' => $age,
        'extra' => $extraInfo
    ];
}

print_r(createPerson('Alice', 30, 'Developer', 'London', 'alice@example.com'));

// Comparison with old-style variadic functions
function oldSumAll() {
    $numbers = func_get_args();
    return array_sum($numbers);
}

echo oldSumAll(1, 2, 3) . "\n";

This example shows the splat operator used in variadic functions. The sumAll function accepts any number of arguments, while concatenate enforces string types. The createPerson function demonstrates mixing regular and variadic parameters.

Argument unpacking

The splat operator can unpack arrays into individual arguments when calling functions. This is useful when you have an array of values that need to be passed as separate arguments to a function.

argument_unpacking.php
<?php

declare(strict_types=1);

// Function that takes three parameters
function formatDate(int $day, string $month, int $year): string {
    return "$day $month $year";
}

$dateParts = [15, 'June', 2025];
echo formatDate(...$dateParts) . "\n";

// With associative arrays (PHP 8.0+)
function createUser(string $name, string $email, int $age = 18): array {
    return compact('name', 'email', 'age');
}

$userData = ['name' => 'Alice', 'email' => 'alice@example.com', 'age' => 30];
print_r(createUser(...$userData));

// Unpacking multiple arrays
function mergeConfigs(array ...$configs): array {
    return array_merge(...$configs);
}

$defaults = ['timeout' => 30, 'debug' => false];
$custom = ['debug' => true, 'log_level' => 'error'];
$merged = mergeConfigs($defaults, $custom);
print_r($merged);

// With generators
function generateNumbers(int $start, int $end): Generator {
    for ($i = $start; $i <= $end; $i++) {
        yield $i;
    }
}

$numbers = [...generateNumbers(1, 5)];
print_r($numbers);

This demonstrates array unpacking with the splat operator. The formatDate example shows positional unpacking, while createUser demonstrates named argument unpacking (PHP 8.0+). The mergeConfigs function shows variadic unpacking, and the generator example converts yielded values to an array.

Array operations with splat

The splat operator simplifies many array operations by providing a concise way to merge arrays or insert multiple elements into an array at once.

array_operations.php
<?php

declare(strict_types=1);

// Merging arrays
$front = ['a', 'b', 'c'];
$back = ['x', 'y', 'z'];
$combined = [...$front, ...$back];
print_r($combined);

// Inserting elements
$middle = ['d', 'e', 'f'];
$fullAlphabet = [...$front, ...$middle, ...$back];
print_r($fullAlphabet);

// With associative arrays (PHP 8.1+)
$defaults = ['color' => 'red', 'size' => 'medium'];
$overrides = ['color' => 'blue', 'price' => 10];
$result = [...$defaults, ...$overrides];
print_r($result);

// Creating new arrays with additional elements
$numbers = [1, 2, 3];
$moreNumbers = [0, ...$numbers, 4, 5];
print_r($moreNumbers);

// Combining with array_merge
$array1 = [1, 2, 3];
$array2 = [4, 5, 6];
$array3 = [7, 8, 9];

$merged = array_merge($array1, $array2, $array3);
$mergedWithSplat = [...$array1, ...$array2, ...$array3];
var_dump($merged === $mergedWithSplat); // true

These examples show how the splat operator simplifies array manipulation. It provides a more readable alternative to array_merge and allows for flexible array construction by spreading elements from multiple arrays.

Practical Use Cases of the Splat Operator

The following examples demonstrate five practical applications of the splat operator, each accompanied by code and detailed explanations to illustrate its power and utility in real-world PHP development.

practical_uses.php
<?php

declare(strict_types=1);

// 1. Flexible Logging with Contextual Data
function debugLog(string $message, ...$context): void {
    $timestamp = date('Y-m-d H:i:s');
    $contextJson = !empty($context) ? json_encode($context) : '';
    echo "[$timestamp] $message $contextJson\n";
}

debugLog('User logged in', ['user_id' => 123, 'ip' => '192.168.1.1']);

// 2. Modular Data Processing Pipeline
function processData(array $data, callable ...$processors): array {
    $result = $data;
    foreach ($processors as $processor) {
        $result = array_map($processor, $result);
    }
    return $result;
}

$numbers = [1, 2, 3, 4, 5];
$processed = processData(
    $numbers,
    fn($n) => $n * 2,
    fn($n) => $n + 1,
    fn($n) => $n ** 2
);
print_r($processed);

// 3. Configuration Merging with Safe Overrides
function createConfig(array $defaults, array ...$overrides): array {
    $config = $defaults;
    foreach ($overrides as $override) {
        $config = array_merge($config, $override);
    }
    return $config;
}

$appConfig = createConfig(
    ['debug' => false, 'timeout' => 30],
    ['debug' => true, 'environment' => 'production']
);
print_r($appConfig);

// 4. Flexible Data Transfer Objects (DTOs)
class ProductDTO {
    public string $name;
    public float $price;
    private array $extra;

    public function __construct(string $name, float $price, array $extra = []) {
        $this->name = $name;
        $this->price = $price;
        $this->extra = $extra;
    }

    public function getExtra(string $key): mixed {
        return $this->extra[$key] ?? null;
    }

    public function getAllExtra(): array {
        return $this->extra;
    }
}

$product = new ProductDTO('Laptop', 999.99, ['category' => 'Electronics', 'stock' => 5]);
print_r($product->getAllExtra());

// 5. Dynamic SQL Query Building
class QueryBuilder {
    private array $parts = [];

    public function select(string ...$columns): self {
        $this->parts['select'] = $columns ?: ['*'];
        return $this;
    }

    public function where(string ...$conditions): self {
        if (!empty($conditions)) {
            $this->parts['where'] = $conditions;
        }
        return $this;
    }

    public function getQuery(): string {
        $select = implode(', ', $this->parts['select'] ?? ['*']);
        $where = isset($this->parts['where']) ? ' WHERE ' . implode(' AND ', $this->parts['where']) : '';
        return "SELECT $select FROM products$where";
    }
}

$query = (new QueryBuilder())
    ->select('id', 'name', 'price')
    ->where('price > 100', 'stock > 0')
    ->getQuery();

echo $query . "\n";

The debugLog function exemplifies how the splat operator facilitates flexible logging with contextual data. By allowing any number of context arrays to be passed as arguments, the function can serialize them into JSON for inclusion in log messages. This is particularly useful for debugging user actions or system events, as it accommodates varying amounts of metadata—such as user IDs or IP addresses—without requiring predefined parameters. The timestamp ensures logs are traceable, making this approach ideal for monitoring application behavior in development or production environments.

The processData function demonstrates the splat operator's role in creating a modular data processing pipeline. It accepts an array of data and a variable number of callable functions, each applied sequentially to transform the data. In the example, numbers are doubled, incremented, and squared in a chain of operations. This design promotes reusability, as developers can easily add or modify processors without altering the core function. It's particularly valuable for tasks like data normalization or transformation in ETL (Extract, Transform, Load) processes.

Configuration management is streamlined with the createConfig function, which uses the splat operator to merge multiple override arrays into a default configuration. This ensures that default settings, such as debug mode or timeouts, are preserved while allowing flexible overrides for specific environments. The use of array_merge with variable arguments prevents unintended overwrites, making it a robust solution for managing application settings across different deployment scenarios.

The ProductDTO class showcases how the splat operator supports flexible Data Transfer Objects. By storing additional attributes in a private extra array, the class avoids dynamic property creation, ensuring compatibility with modern PHP's strict standards. The getExtra and getAllExtra methods provide safe access to these attributes, allowing developers to handle variable data—like product categories or stock levels—while maintaining type safety and encapsulation.

Finally, the QueryBuilder class illustrates the splat operator's utility in building dynamic SQL queries. By accepting variable numbers of columns and conditions, it creates a fluent interface for constructing queries. The example selects specific columns and applies multiple conditions, producing a clean SQL statement. This approach simplifies database interactions, making it easier to build complex queries while keeping the code readable and maintainable, especially in applications with dynamic data requirements.

PHP's splat operator (...) is a versatile tool for working with variable-length argument lists and array manipulation. Key points to remember:

The splat operator is particularly valuable when creating flexible APIs, processing variable-length data, or combining arrays. It makes PHP code more expressive while maintaining good performance characteristics.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all PHP tutorials.