func_num_args
Returns how many arguments were actually passed to the current function.
func_num_args(): int- Added in PHP 4.0
Return value
intThe number of arguments passed into the current user-defined function.
Errors
Throws an Error if called from the global scope or invoked dynamically (for example through call_user_func).
Changelog
- PHP 8.0Named arguments are counted as if passed positionally, and skipped parameters before the last supplied one are counted with their defaults. Unknown named variadic arguments are not counted.
func_num_args() tells you how many arguments the current function received. Its most valuable use has nothing to do with variadics: it is the standard way to distinguish "the caller did not pass this argument" from "the caller passed null".
The null-versus-omitted problem
A parameter declared ?string $value = null looks identical inside the function whether the caller wrote set('key') or set('key', null). For a setter, a cache API or a config object those two mean opposite things: leave it alone versus clear it. Comparing func_num_args() against the parameter position resolves it without inventing a sentinel default such as a magic constant or a private marker object.
Other uses
It also guards func_get_arg() loops so you never hit the ValueError that an out-of-range position throws, and it lets a legacy function change behaviour based on arity, the way implode() historically did.
Watch the PHP 8 counting rules
Named arguments are normalised to positional, so skipping a middle parameter still counts it. f(c: 1) on a three-parameter function reports 3, not 1.
Example
When to use it
- Telling apart a setter called with an explicit null from one called with the argument omitted
- Guarding a func_get_arg() loop so it never asks for an out-of-range position
- Changing behaviour by arity in a legacy function whose signature cannot be widened
- Warning at runtime when a deprecated extra argument is still being passed
Frequently asked questions
How do I tell whether an optional argument was actually passed?
Compare func_num_args() with the parameter's one-based position: if the count is lower, the argument was omitted. This is the only reliable way to distinguish an omitted argument from an explicitly passed null.
Does func_num_args count parameters with default values?
Only up to the last argument the caller actually supplied. Since PHP 8, however, a named argument makes every earlier parameter count too, so f(c: 1) reports 3 on a three-parameter function.
Can I call func_num_args outside a function?
No. Calling it from the global scope, or indirectly through something like call_user_func(), throws an Error because it needs the calling function's frame.
More examples
Behaviour that depends on arity
Prints 'range 0..5', 'range 5..9' and 'range 5..0'. The third call passes the same value as the default, but func_num_args() still reports 2, so the two-argument branch runs — something a default-value comparison could never detect.
<?php
function between(int $a, int $b = 0): string
{
if (func_num_args() === 1) {
return "range 0..$a";
}
return "range $a..$b";
}
echo between(5), "\n";
echo between(5, 9), "\n";
echo between(5, 0), "\n";Named arguments inflate the count
Prints 0, 1, 3 and 2. Passing c by name forces a and b to be filled in with defaults and counted, so the count reflects the highest position reached rather than the number of names the caller typed.
<?php
function arity(string $a = 'A', string $b = 'B', string $c = 'C'): int
{
return func_num_args();
}
echo arity(), "\n";
echo arity('x'), "\n";
echo arity(c: 'z'), "\n";
echo arity(b: 'y'), "\n";Guarding a func_get_arg loop
Prints 10 and 0. Caching the count in $n before the loop keeps the index strictly below the number of arguments, so func_get_arg() never throws the ValueError it raises for an out-of-range position.
<?php
function sumAll(): int
{
$total = 0;
for ($i = 0, $n = func_num_args(); $i < $n; $i++) {
$total += (int) func_get_arg($i);
}
return $total;
}
echo sumAll(1, 2, 3, 4), "\n";
echo sumAll(), "\n";
Discussion