Variadic Functions
# # Variadic Functions What Is a Variadic Function? In simple terms: A variadic function accepts any number of arguments. Instead of declaring a fixed list of parameters, you declare one parameter tha
# # Variadic Functions
What Is a Variadic Function?
In simple terms: A variadic function accepts any number of arguments. Instead of declaring a fixed list of parameters, you declare one parameter that collects all remaining arguments into an array.
Technically: A parameter prefixed with ... (the splat or spread operator) is a variadic parameter. When the function is called, all remaining positional arguments are collected into an array and assigned to that parameter.
function sum(int ...$numbers): int // $numbers is an array of all passed integers
Why Variadic Functions Exist
Some operations naturally work on "one or more" or "zero or more" values: adding numbers, joining words, logging a message with any number of details, or finding the maximum. PHP's own max(), min(), printf(), and array_merge() work this way. Variadic parameters let your functions do the same.
Syntax
function functionName(Type $required, Type ...$rest)
{
// $rest is an array of the remaining arguments
}
Example
<?php
function sum(int ...$numbers): int
{
$total = 0;
foreach ($numbers as $number) {
$total += $number;
}
return $total;
}
echo sum(1, 2, 3) . "\n";
echo sum(10, 20, 30, 40, 50) . "\n";
echo sum() . "\n";
Output
6
150
0
How It Works
...$numberscollects all arguments into an array:sum(1, 2, 3)gives$numbers = [1, 2, 3].- Calling
sum()with no arguments gives an empty array, so the loop does not run and the result is0. - The type
intapplies to each collected argument. Passing a non-integer value that cannot be converted causes aTypeError.
(The body could simply be return array_sum($numbers); — the loop is shown to make the collected array visible.)
Combining Regular and Variadic Parameters
Regular parameters come first; the variadic parameter must be last, and there can be only one.
<?php
function joinWords(string $separator, string ...$words): string
{
return implode($separator, $words);
}
echo joinWords(', ', 'PHP', 'MySQL', 'Laravel') . "\n";
echo joinWords(' | ', 'Home', 'Courses') . "\n";
Output
PHP, MySQL, Laravel
Home | Courses
The first argument always goes to $separator; every argument after it goes into $words.
Requiring at Least One Value
A variadic parameter accepts zero arguments. To require at least one, declare the first value as a normal parameter:
<?php
function maxOf(int $first, int ...$others): int
{
return max($first, ...$others);
}
echo maxOf(3, 9, 4) . "\n";
echo maxOf(7) . "\n";
Output
9
7
Calling maxOf() with no arguments now throws an ArgumentCountError, which is correct — the maximum of nothing is undefined. Inside the function, ...$others unpacks the array again for max() (explained below).
Argument Unpacking: ... in Function Calls
The same ... operator works in the opposite direction in a call: it spreads an array (or other iterable) into separate arguments.
<?php
function sum(int ...$numbers): int
{
return array_sum($numbers);
}
$cartPrices = [499, 1299];
$extraCharges = [100];
echo sum(...$cartPrices) . "\n";
echo sum(...$cartPrices, ...$extraCharges) . "\n";
echo sum(5, ...$cartPrices) . "\n";
$dateParts = [2026, 10, 15];
$date = new DateTimeImmutable();
echo $date->setDate(...$dateParts)->format('Y-m-d') . "\n";
Output
1798
1898
1803
2026-10-15
How It Works
sum(...$cartPrices)is equivalent tosum(499, 1299).- Several arrays can be unpacked in one call, and normal arguments can come before an unpacked array.
- Unpacking works with any function, not only variadic ones:
setDate(...[2026, 10, 15])passes three separate arguments tosetDate($year, $month, $day).
Rule: In a call, a normal positional argument cannot come after an unpacked array.
sum(...$cartPrices, 5)is a compile-time error ("Cannot use positional argument after argument unpacking"). Put the extra value first, or unpack[5]as another array.
Unpacking Arrays With String Keys (PHP 8.1+)
When an unpacked array has string keys, they are treated as named arguments:
<?php
function createUser(string $name, string $role = 'viewer'): string
{
return "$name ($role)";
}
$data = ['name' => 'Asha', 'role' => 'admin'];
echo createUser(...$data) . "\n";
Output
Asha (admin)
Variadics and Named Arguments
A variadic parameter also collects named arguments that do not match a declared parameter, using the names as string keys:
<?php
function buildQuery(string $path, string|int ...$params): string
{
return $params === [] ? $path : $path . '?' . http_build_query($params);
}
echo buildQuery('/search') . "\n";
echo buildQuery('/search', q: 'php arrays', page: 2) . "\n";
Output
/search
/search?q=php+arrays&page=2
q and page are not declared parameters, so they are collected into $params as ['q' => 'php arrays', 'page' => 2].
Variadic Parameters by Reference
Adding & makes each collected argument a reference to the caller's variable:
<?php
function trimAll(string &...$values): void
{
foreach ($values as &$value) {
$value = trim($value);
}
unset($value);
}
$name = ' Asha ';
$city = ' Chennai ';
trimAll($name, $city);
var_dump($name, $city);
Output
string(4) "Asha"
string(7) "Chennai"
Each argument must be a variable. As with other reference parameters, use this sparingly — returning new values is usually clearer.
Practical Example: A Formatted Logger
<?php
function logMessage(string $level, string $format, string|int|float ...$values): string
{
$message = sprintf($format, ...$values);
return sprintf('[%s] %-7s %s', '2026-10-09 10:15', strtoupper($level), $message);
}
echo logMessage('info', 'User %s logged in from %s', 'asha', '10.0.0.5') . "\n";
echo logMessage('warning', 'Disk usage at %d%%', 91) . "\n";
echo logMessage('error', 'Payment %s failed after %d attempts', 'PAY-889', 3) . "\n";
Output
[2026-10-09 10:15] INFO User asha logged in from 10.0.0.5
[2026-10-09 10:15] WARNING Disk usage at 91%
[2026-10-09 10:15] ERROR Payment PAY-889 failed after 3 attempts
Step-by-Step Explanation
$leveland$formatare required; any number of values follow.sprintf($format, ...$values)unpacks the collected values back into separate arguments forsprintf(), which fills the placeholders.%-7sleft-aligns the level in a 7-character column so messages line up.- The timestamp is fixed here to keep the output predictable; a real logger would use
date('Y-m-d H:i').
The variadic parameter lets one function handle messages with zero, one, or many values, with type checking on each value.
Legacy Alternative: func_get_args()
Before PHP 5.6 introduced ..., functions read extra arguments with func_get_args():
function oldSum()
{
return array_sum(func_get_args());
}
This still works, but the signature hides the fact that the function accepts arguments, and there is no type checking. Use variadic parameters in modern code.
Common Mistakes
Placing the Variadic Parameter Before Others
function report(string ...$lines, string $title) { } // compile error
Fix: The variadic parameter must be the last parameter.
Passing an Array Instead of Unpacking It
<?php
function sum(int ...$numbers): int
{
return array_sum($numbers);
}
$prices = [499, 1299];
echo sum($prices); // TypeError: an array is not an int
Fix: sum(...$prices).
Forgetting That Zero Arguments Are Allowed
Effect: Code inside the function assumes at least one value (for example, $values[0]) and fails on an empty array.
Fix: Handle the empty case, or require the first value as a normal parameter.
Positional Arguments After Unpacking
Effect: Compile-time error.
Fix: Place normal arguments before ...$array.
Best Practices
- Use variadic parameters for "zero or more" or "one or more" values of the same kind.
- Type the variadic parameter so every value is checked.
- Require a first value explicitly when an empty call makes no sense.
- Use
...in calls to unpack arrays instead ofcall_user_func_array(). - Prefer an explicit
arrayparameter when callers naturally already have an array and the values are not a simple list of arguments.
Official reference: https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list
What Is a Variadic Function?
In simple terms: A variadic function accepts any number of arguments. Instead of declaring a fixed list of parameters, you declare one parameter that collects all remaining arguments into an array.
Technically: A parameter prefixed with ... (the splat or spread operator) is a variadic parameter. When the function is called, all remaining positional arguments are collected into an array and assigned to that parameter.
function sum(int ...$numbers): int // $numbers is an array of all passed integers
Why Variadic Functions Exist
Some operations naturally work on "one or more" or "zero or more" values: adding numbers, joining words, logging a message with any number of details, or finding the maximum. PHP's own max(), min(), printf(), and array_merge() work this way. Variadic parameters let your functions do the same.
Syntax
function functionName(Type $required, Type ...$rest)
{
// $rest is an array of the remaining arguments
}
Example
<?php
function sum(int ...$numbers): int
{
$total = 0;
foreach ($numbers as $number) {
$total += $number;
}
return $total;
}
echo sum(1, 2, 3) . "\n";
echo sum(10, 20, 30, 40, 50) . "\n";
echo sum() . "\n";
Output
6
150
0
How It Works
...$numberscollects all arguments into an array:sum(1, 2, 3)gives$numbers = [1, 2, 3].- Calling
sum()with no arguments gives an empty array, so the loop does not run and the result is0. - The type
intapplies to each collected argument. Passing a non-integer value that cannot be converted causes aTypeError.
(The body could simply be return array_sum($numbers); — the loop is shown to make the collected array visible.)
Combining Regular and Variadic Parameters
Regular parameters come first; the variadic parameter must be last, and there can be only one.
<?php
function joinWords(string $separator, string ...$words): string
{
return implode($separator, $words);
}
echo joinWords(', ', 'PHP', 'MySQL', 'Laravel') . "\n";
echo joinWords(' | ', 'Home', 'Courses') . "\n";
Output
PHP, MySQL, Laravel
Home | Courses
The first argument always goes to $separator; every argument after it goes into $words.
Requiring at Least One Value
A variadic parameter accepts zero arguments. To require at least one, declare the first value as a normal parameter:
<?php
function maxOf(int $first, int ...$others): int
{
return max($first, ...$others);
}
echo maxOf(3, 9, 4) . "\n";
echo maxOf(7) . "\n";
Output
9
7
Calling maxOf() with no arguments now throws an ArgumentCountError, which is correct — the maximum of nothing is undefined. Inside the function, ...$others unpacks the array again for max() (explained below).
Argument Unpacking: ... in Function Calls
The same ... operator works in the opposite direction in a call: it spreads an array (or other iterable) into separate arguments.
<?php
function sum(int ...$numbers): int
{
return array_sum($numbers);
}
$cartPrices = [499, 1299];
$extraCharges = [100];
echo sum(...$cartPrices) . "\n";
echo sum(...$cartPrices, ...$extraCharges) . "\n";
echo sum(5, ...$cartPrices) . "\n";
$dateParts = [2026, 10, 15];
$date = new DateTimeImmutable();
echo $date->setDate(...$dateParts)->format('Y-m-d') . "\n";
Output
1798
1898
1803
2026-10-15
How It Works
sum(...$cartPrices)is equivalent tosum(499, 1299).- Several arrays can be unpacked in one call, and normal arguments can come before an unpacked array.
- Unpacking works with any function, not only variadic ones:
setDate(...[2026, 10, 15])passes three separate arguments tosetDate($year, $month, $day).
Rule: In a call, a normal positional argument cannot come after an unpacked array.
sum(...$cartPrices, 5)is a compile-time error ("Cannot use positional argument after argument unpacking"). Put the extra value first, or unpack[5]as another array.
Unpacking Arrays With String Keys (PHP 8.1+)
When an unpacked array has string keys, they are treated as named arguments:
<?php
function createUser(string $name, string $role = 'viewer'): string
{
return "$name ($role)";
}
$data = ['name' => 'Asha', 'role' => 'admin'];
echo createUser(...$data) . "\n";
Output
Asha (admin)
Variadics and Named Arguments
A variadic parameter also collects named arguments that do not match a declared parameter, using the names as string keys:
<?php
function buildQuery(string $path, string|int ...$params): string
{
return $params === [] ? $path : $path . '?' . http_build_query($params);
}
echo buildQuery('/search') . "\n";
echo buildQuery('/search', q: 'php arrays', page: 2) . "\n";
Output
/search
/search?q=php+arrays&page=2
q and page are not declared parameters, so they are collected into $params as ['q' => 'php arrays', 'page' => 2].
Variadic Parameters by Reference
Adding & makes each collected argument a reference to the caller's variable:
<?php
function trimAll(string &...$values): void
{
foreach ($values as &$value) {
$value = trim($value);
}
unset($value);
}
$name = ' Asha ';
$city = ' Chennai ';
trimAll($name, $city);
var_dump($name, $city);
Output
string(4) "Asha"
string(7) "Chennai"
Each argument must be a variable. As with other reference parameters, use this sparingly — returning new values is usually clearer.
Practical Example: A Formatted Logger
<?php
function logMessage(string $level, string $format, string|int|float ...$values): string
{
$message = sprintf($format, ...$values);
return sprintf('[%s] %-7s %s', '2026-10-09 10:15', strtoupper($level), $message);
}
echo logMessage('info', 'User %s logged in from %s', 'asha', '10.0.0.5') . "\n";
echo logMessage('warning', 'Disk usage at %d%%', 91) . "\n";
echo logMessage('error', 'Payment %s failed after %d attempts', 'PAY-889', 3) . "\n";
Output
[2026-10-09 10:15] INFO User asha logged in from 10.0.0.5
[2026-10-09 10:15] WARNING Disk usage at 91%
[2026-10-09 10:15] ERROR Payment PAY-889 failed after 3 attempts
Step-by-Step Explanation
$leveland$formatare required; any number of values follow.sprintf($format, ...$values)unpacks the collected values back into separate arguments forsprintf(), which fills the placeholders.%-7sleft-aligns the level in a 7-character column so messages line up.- The timestamp is fixed here to keep the output predictable; a real logger would use
date('Y-m-d H:i').
The variadic parameter lets one function handle messages with zero, one, or many values, with type checking on each value.
Legacy Alternative: func_get_args()
Before PHP 5.6 introduced ..., functions read extra arguments with func_get_args():
function oldSum()
{
return array_sum(func_get_args());
}
This still works, but the signature hides the fact that the function accepts arguments, and there is no type checking. Use variadic parameters in modern code.
Common Mistakes
Placing the Variadic Parameter Before Others
function report(string ...$lines, string $title) { } // compile error
Fix: The variadic parameter must be the last parameter.
Passing an Array Instead of Unpacking It
<?php
function sum(int ...$numbers): int
{
return array_sum($numbers);
}
$prices = [499, 1299];
echo sum($prices); // TypeError: an array is not an int
Fix: sum(...$prices).
Forgetting That Zero Arguments Are Allowed
Effect: Code inside the function assumes at least one value (for example, $values[0]) and fails on an empty array.
Fix: Handle the empty case, or require the first value as a normal parameter.
Positional Arguments After Unpacking
Effect: Compile-time error.
Fix: Place normal arguments before ...$array.
Best Practices
- Use variadic parameters for "zero or more" or "one or more" values of the same kind.
- Type the variadic parameter so every value is checked.
- Require a first value explicitly when an empty call makes no sense.
- Use
...in calls to unpack arrays instead ofcall_user_func_array(). - Prefer an explicit
arrayparameter when callers naturally already have an array and the values are not a simple list of arguments.
Official reference: https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list
What Is a Variadic Function?
In simple terms: A variadic function accepts any number of arguments. Instead of declaring a fixed list of parameters, you declare one parameter that collects all remaining arguments into an array.
Technically: A parameter prefixed with ... (the splat or spread operator) is a variadic parameter. When the function is called, all remaining positional arguments are collected into an array and assigned to that parameter.
function sum(int ...$numbers): int // $numbers is an array of all passed integers
Why Variadic Functions Exist
Some operations naturally work on "one or more" or "zero or more" values: adding numbers, joining words, logging a message with any number of details, or finding the maximum. PHP's own max(), min(), printf(), and array_merge() work this way. Variadic parameters let your functions do the same.
Syntax
function functionName(Type $required, Type ...$rest)
{
// $rest is an array of the remaining arguments
}
Example
<?php
function sum(int ...$numbers): int
{
$total = 0;
foreach ($numbers as $number) {
$total += $number;
}
return $total;
}
echo sum(1, 2, 3) . "\n";
echo sum(10, 20, 30, 40, 50) . "\n";
echo sum() . "\n";
Output
6
150
0
How It Works
...$numberscollects all arguments into an array:sum(1, 2, 3)gives$numbers = [1, 2, 3].- Calling
sum()with no arguments gives an empty array, so the loop does not run and the result is0. - The type
intapplies to each collected argument. Passing a non-integer value that cannot be converted causes aTypeError.
(The body could simply be return array_sum($numbers); — the loop is shown to make the collected array visible.)
Combining Regular and Variadic Parameters
Regular parameters come first; the variadic parameter must be last, and there can be only one.
<?php
function joinWords(string $separator, string ...$words): string
{
return implode($separator, $words);
}
echo joinWords(', ', 'PHP', 'MySQL', 'Laravel') . "\n";
echo joinWords(' | ', 'Home', 'Courses') . "\n";
Output
PHP, MySQL, Laravel
Home | Courses
The first argument always goes to $separator; every argument after it goes into $words.
Requiring at Least One Value
A variadic parameter accepts zero arguments. To require at least one, declare the first value as a normal parameter:
<?php
function maxOf(int $first, int ...$others): int
{
return max($first, ...$others);
}
echo maxOf(3, 9, 4) . "\n";
echo maxOf(7) . "\n";
Output
9
7
Calling maxOf() with no arguments now throws an ArgumentCountError, which is correct — the maximum of nothing is undefined. Inside the function, ...$others unpacks the array again for max() (explained below).
Argument Unpacking: ... in Function Calls
The same ... operator works in the opposite direction in a call: it spreads an array (or other iterable) into separate arguments.
<?php
function sum(int ...$numbers): int
{
return array_sum($numbers);
}
$cartPrices = [499, 1299];
$extraCharges = [100];
echo sum(...$cartPrices) . "\n";
echo sum(...$cartPrices, ...$extraCharges) . "\n";
echo sum(5, ...$cartPrices) . "\n";
$dateParts = [2026, 10, 15];
$date = new DateTimeImmutable();
echo $date->setDate(...$dateParts)->format('Y-m-d') . "\n";
Output
1798
1898
1803
2026-10-15
How It Works
sum(...$cartPrices)is equivalent tosum(499, 1299).- Several arrays can be unpacked in one call, and normal arguments can come before an unpacked array.
- Unpacking works with any function, not only variadic ones:
setDate(...[2026, 10, 15])passes three separate arguments tosetDate($year, $month, $day).
Rule: In a call, a normal positional argument cannot come after an unpacked array.
sum(...$cartPrices, 5)is a compile-time error ("Cannot use positional argument after argument unpacking"). Put the extra value first, or unpack[5]as another array.
Unpacking Arrays With String Keys (PHP 8.1+)
When an unpacked array has string keys, they are treated as named arguments:
<?php
function createUser(string $name, string $role = 'viewer'): string
{
return "$name ($role)";
}
$data = ['name' => 'Asha', 'role' => 'admin'];
echo createUser(...$data) . "\n";
Output
Asha (admin)
Variadics and Named Arguments
A variadic parameter also collects named arguments that do not match a declared parameter, using the names as string keys:
<?php
function buildQuery(string $path, string|int ...$params): string
{
return $params === [] ? $path : $path . '?' . http_build_query($params);
}
echo buildQuery('/search') . "\n";
echo buildQuery('/search', q: 'php arrays', page: 2) . "\n";
Output
/search
/search?q=php+arrays&page=2
q and page are not declared parameters, so they are collected into $params as ['q' => 'php arrays', 'page' => 2].
Variadic Parameters by Reference
Adding & makes each collected argument a reference to the caller's variable:
<?php
function trimAll(string &...$values): void
{
foreach ($values as &$value) {
$value = trim($value);
}
unset($value);
}
$name = ' Asha ';
$city = ' Chennai ';
trimAll($name, $city);
var_dump($name, $city);
Output
string(4) "Asha"
string(7) "Chennai"
Each argument must be a variable. As with other reference parameters, use this sparingly — returning new values is usually clearer.
Practical Example: A Formatted Logger
<?php
function logMessage(string $level, string $format, string|int|float ...$values): string
{
$message = sprintf($format, ...$values);
return sprintf('[%s] %-7s %s', '2026-10-09 10:15', strtoupper($level), $message);
}
echo logMessage('info', 'User %s logged in from %s', 'asha', '10.0.0.5') . "\n";
echo logMessage('warning', 'Disk usage at %d%%', 91) . "\n";
echo logMessage('error', 'Payment %s failed after %d attempts', 'PAY-889', 3) . "\n";
Output
[2026-10-09 10:15] INFO User asha logged in from 10.0.0.5
[2026-10-09 10:15] WARNING Disk usage at 91%
[2026-10-09 10:15] ERROR Payment PAY-889 failed after 3 attempts
Step-by-Step Explanation
$leveland$formatare required; any number of values follow.sprintf($format, ...$values)unpacks the collected values back into separate arguments forsprintf(), which fills the placeholders.%-7sleft-aligns the level in a 7-character column so messages line up.- The timestamp is fixed here to keep the output predictable; a real logger would use
date('Y-m-d H:i').
The variadic parameter lets one function handle messages with zero, one, or many values, with type checking on each value.
Legacy Alternative: func_get_args()
Before PHP 5.6 introduced ..., functions read extra arguments with func_get_args():
function oldSum()
{
return array_sum(func_get_args());
}
This still works, but the signature hides the fact that the function accepts arguments, and there is no type checking. Use variadic parameters in modern code.
Common Mistakes
Placing the Variadic Parameter Before Others
function report(string ...$lines, string $title) { } // compile error
Fix: The variadic parameter must be the last parameter.
Passing an Array Instead of Unpacking It
<?php
function sum(int ...$numbers): int
{
return array_sum($numbers);
}
$prices = [499, 1299];
echo sum($prices); // TypeError: an array is not an int
Fix: sum(...$prices).
Forgetting That Zero Arguments Are Allowed
Effect: Code inside the function assumes at least one value (for example, $values[0]) and fails on an empty array.
Fix: Handle the empty case, or require the first value as a normal parameter.
Positional Arguments After Unpacking
Effect: Compile-time error.
Fix: Place normal arguments before ...$array.
Best Practices
- Use variadic parameters for "zero or more" or "one or more" values of the same kind.
- Type the variadic parameter so every value is checked.
- Require a first value explicitly when an empty call makes no sense.
- Use
...in calls to unpack arrays instead ofcall_user_func_array(). - Prefer an explicit
arrayparameter when callers naturally already have an array and the values are not a simple list of arguments.
Official reference: https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list