Difference Between func_get_args and Variadics in PHP

This article compares the traditional func_get_args() function with the modern variadic arguments syntax (... operator) in PHP. We will explore how both methods handle variable-length argument lists, highlight their key differences in syntax, readability, and performance, and explain why one has become the standard in modern PHP development.

Historically, PHP developers used func_get_args() to create functions that could accept an arbitrary number of arguments. Introduced in PHP 5.6, variadic arguments (also known as the splat or spread operator) offered a more modern, readable, and feature-rich alternative.

1. Syntax and Function Signatures

The most obvious difference lies in how these two features are declared and read in code.

Using func_get_args(), the function signature does not indicate that the function accepts dynamic arguments. You must look inside the function body to find out:

function sumAll() {
    $args = func_get_args();
    return array_sum($args);
}

With variadic arguments, the dynamic parameter is explicitly declared in the function signature using the ... prefix:

function sumAll(...$numbers) {
    return array_sum($numbers);
}

The variadic signature makes the code self-documenting, immediately informing developers and IDEs that the function accepts multiple arguments.

2. Capturing Specific vs. Remaining Arguments

When using func_get_args(), the function always returns all arguments passed to the function. If you want to capture specific named arguments and group the rest, you must manually slice the array:

function buildProfile($name, $age) {
    $hobbies = array_slice(func_get_args(), 2);
    // $name and $age must be manually skipped
}

Variadic arguments solve this cleanly. You can place the variadic parameter at the end of the argument list to automatically capture only the “remaining” arguments:

function buildProfile($name, $age, ...$hobbies) {
    // $hobbies only contains the arguments passed after $age
}

3. Type Hinting

Variadic arguments fully support PHP type hinting. You can enforce that all dynamically passed arguments belong to a specific data type:

function concatenate(string ...$strings) {
    return implode('', $strings);
}

If you pass a non-string value to the concatenate function, PHP will throw a TypeError. Achieving this same behavior with func_get_args() requires writing manual loops and type-checking logic inside the function body.

4. Passing Arguments by Reference

Variadic arguments allow you to pass dynamic arguments by reference by prepending an ampersand (&) to the operator:

function addOneToAll(&...$numbers) {
    foreach ($numbers as &$number) {
        $number++;
    }
}

func_get_args() cannot easily handle pass-by-reference arguments because it returns a copy of the passed arguments, meaning any modifications to the returned array will not affect the original variables.

5. Performance

Under the hood, variadic arguments are faster and more memory-efficient than func_get_args(). Because func_get_args() is a function call, it incurs the overhead of a standard function call execution. Variadic arguments are handled directly by the PHP engine compiler, resulting in better performance, especially in loops or high-frequency function executions.