In PHP 8, how do named arguments let a caller skip optional parameters, and which errors can a named-argument call raise?
answer
- name: value after positional ones
- order-independent, skip any default
- Unknown named parameter $x
- overwrites previous argument
- positional after named: compile error
basics
~20 sSince PHP 8.0 a call can pass name: value, matched by parameter name, so any optional parameter can be skipped in any order. An unknown or repeated name throws Error; a positional argument after a named one fails at compile time.
solid answer
~40 sNamed arguments, added in PHP 8.0, match a value to a parameter by its **name**: `buildReport('2026-Q3', format: 'json')`. They are order-independent and let you skip any optional parameter without restating the defaults before it, which is what makes a function with many optional filters usable. They may follow positional arguments, never precede them: `f(a: 1, 2)` is a compile-time `Cannot use positional argument after named argument`. At runtime, a name the function does not declare throws `Error: Unknown named parameter $formt`; naming a parameter already filled positionally throws `Error: Named parameter $period overwrites previous argument`; and a required parameter left out throws `ArgumentCountError` (`Argument #1 ($period) not passed`). Built-in functions take them too, using the parameter names in the manual.
code
php · 19 lines<?php
declare(strict_types=1);
function buildReport(
string $period,
?string $region = null,
?string $product = null,
int $minRevenue = 0,
bool $includeRefunds = false,
string $format = 'csv',
): string {
return sprintf('%s/%s/%s/%d/%s/%s', $period, $region ?? '*', $product ?? '*',
$minRevenue, $includeRefunds ? 'refunds' : 'net', $format);
}
// Positional: every default before $format must be repeated
echo buildReport('2026-Q3', null, null, 0, false, 'json'), "\n"; // 2026-Q3/*/*/0/net/json
// Named: only what differs, in any order
echo buildReport('2026-Q3', format: 'json', region: 'EU'), "\n"; // 2026-Q3/EU/*/0/net/jsongo deeper
Recall the name: value syntax, that named arguments come after positional ones, and that they let you skip optional parameters.
Explain each failure: unknown name, overwrite, missing required parameter, positional after named, and which of them are catchable at runtime.
Show where named arguments pay off, such as long optional lists and boolean flags, and how variadic option bags hide typos you would otherwise catch.
Judge whether an API should invite named calls at all, since every parameter name then becomes a contract you must keep.
## What named arguments are Before PHP 8.0 every argument was **positional**: the first value went to the first parameter, the second to the second, and so on. PHP 8.0 added **named arguments**, written `parameterName: value` at the call site. The engine matches each one to the parameter with that name, so: - the call documents itself (`includeRefunds: true` instead of a bare `true`); - order no longer matters among the named ones; - any optional parameter can be skipped, however far down the list it sits. The name is a plain identifier, the parameter's name without the `$`. Reserved words are allowed (`array: $rows`, as in `array_slice(array: $rows, offset: 2)`), but the name cannot come from a variable. ## Skipping defaults in a report builder Picture a report function with one required parameter and five optional filters. Positionally, a caller who only wants JSON output must repeat every default in between: `buildReport('2026-Q3', null, null, 0, false, 'json')`. Each repeated default is a copy that silently goes stale if the function's default changes. With named arguments the caller writes only what differs: `buildReport('2026-Q3', format: 'json', region: 'EU')`. The skipped parameters take their declared defaults. ## Rules for mixing 1. **Positional first, named after.** `buildReport('2026-Q3', format: 'json')` is fine; `buildReport(period: '2026-Q3', 'json')` is rejected when the file compiles. 2. **Each parameter at most once.** A name may not repeat, and may not target a parameter a positional argument already filled. 3. **Required parameters are still required.** Skipping one, by name or by position, throws `ArgumentCountError`. 4. **After unpacking, since PHP 8.1.** `buildReport(...$base, format: 'json')` is allowed, as long as the named argument does not overwrite a value the unpack supplied. ## The errors, side by side | Call (for `buildReport(string $period, ..., string $format = 'csv')`) | Result | Raised | |---|---|---| | `buildReport('2026-Q3', formt: 'json')` | `Error: Unknown named parameter $formt` | at the call | | `buildReport('2026-Q3', period: '2026-Q4')` | `Error: Named parameter $period overwrites previous argument` | at the call | | `buildReport(format: 'json')` | `ArgumentCountError: buildReport(): Argument #1 ($period) not passed` | at the call | | `buildReport(period: '2026-Q3', 'json')` | `Fatal error: Cannot use positional argument after named argument` | at compile time | The first three are thrown objects you can catch; the last stops the file from compiling at all. One exception to the first row: if the function declares a **variadic** parameter (`...$options`), an unknown name is not an error, it is collected into that array under a string key. ## Built-in functions Named arguments work for internal functions as well, with the parameter names from the manual: - `htmlspecialchars($text, double_encode: false)` skips `$flags` and `$encoding`, keeping their defaults. - `array_slice($rows, 1, preserve_keys: true)` skips `$length`. - `str_pad('7', 3, pad_type: STR_PAD_LEFT)` skips `$pad_string`. A few internal parameters have **no default expressible in PHP**. `array_keys($map, strict: true)` throws `ArgumentCountError: array_keys(): Argument #2 ($filter_value) must be passed explicitly, because the default value is not known`; pass `filter_value:` too. ## What named arguments do not do - They do not rename or alias anything: the caller must use the exact name the called function declares. - They cannot target a parameter dynamically. To choose names at runtime, unpack an array with string keys, `buildReport(...$options)`, where each key becomes a named argument and an unknown key throws the same `Unknown named parameter` error. - They do not make a required parameter optional, and since PHP 8.1 they cannot rescue an optional parameter declared before a required one. ## When to reach for them Named arguments earn their place where a positional call would be unreadable or fragile: - **boolean and flag arguments**, where `includeRefunds: true` says what a bare `true` hides; - **long optional lists**, where the caller wants the fifth option and not the four before it; - **built-ins with awkward orders**, such as `htmlspecialchars()` when only `double_encode` differs. They cost something too. Every named call ties the caller to the callee's parameter names, so a rename in the called function breaks the call even though its positional shape is unchanged. For short, obvious signatures such as `max($a, $b)` or `str_contains($haystack, $needle)`, positional calls stay clearer. Many teams therefore use named arguments at call sites that pass flags or skip defaults, and positional ones everywhere else.
- In PHP 8, how can a caller choose argument names at runtime if the name: syntax only takes literal identifiers?Unpack an array with string keys: `buildReport(...['period' => '2026-Q3', $key => $value])`. Each string key is treated as a named argument, integer keys as positional ones, and positional keys must come before string keys. An unknown key throws the same `Error: Unknown named parameter`, and since PHP 8.1 you can add literal named arguments after the unpack.
- Why does array_keys($map, strict: true) throw in PHP 8.5 when array_keys($map) works?The optional `$filter_value` parameter of `array_keys()` has no default that PHP code can express, so it cannot be skipped by name. The call throws `ArgumentCountError: array_keys(): Argument #2 ($filter_value) must be passed explicitly, because the default value is not known`. Passing `filter_value:` along with `strict: true` works.
- What happens to an unknown named argument when the PHP function declares a variadic ...$options parameter?It is not an error. The engine collects every unmatched named argument into the variadic array under its name as a string key, so `f('x', color: 'red')` for `function f($a, ...$options)` gives `$options === ['color' => 'red']`. That is handy for option bags, but a typo is then collected silently instead of throwing.
saying these in an interview costs you the question
- Named arguments may come before positional ones if every name is correct.
- An unknown named argument is ignored, like an extra positional argument.
- Named arguments only work with user-defined functions, not built-ins.
- The parameter name can come from a variable, as in $name: $value.
- Passing a parameter positionally and again by name lets the named value win.