Named arguments are one of the PHP 8.0 features that changed how I write code every single day, quietly, without needing a migration or a version bump to a library. Once a codebase is on 8.0+, you can pass arguments to a function by parameter name instead of position — and the biggest win isn't cleverness, it's turning a call site full of unlabeled booleans into something you can actually read six months later.
The basic syntax
Any call can mix positional and named arguments, as long as positional arguments come first. A named argument uses the parameter's name from the function signature, followed by a colon, followed by the value.
function createUser(
string $name,
string $email,
bool $isAdmin = false,
bool $sendWelcomeEmail = true,
?string $locale = null,
): User {
// ...
}
// Positional — readable only if you have the signature memorized
createUser('Amina Otieno', 'amina@example.com', false, false, 'sw');
// Named — self-documenting at the call site, order doesn't matter
// for the named ones
createUser(
name: 'Amina Otieno',
email: 'amina@example.com',
sendWelcomeEmail: false,
locale: 'sw',
);
Notice the second example skips $isAdmin entirely and still passes $locale — that's the actual headline feature. Before 8.0, skipping an optional middle parameter meant passing its default value explicitly just to get to the one after it, or reordering the function signature so the parameter you actually needed came first. Named arguments let you specify only the parameters that differ from their defaults, in whatever order you like.
Why this matters for flag-heavy calls
The classic PHP readability problem is a call like renderTable($data, true, false, true, 'name') — every boolean is meaningless without opening the function definition. Named arguments turn that back into English at the call site, which matters most for functions with several optional flags, exactly the shape that accumulates in options-heavy APIs, PDF/export generators, and framework helper functions.
// What was there before: which true is which?
renderTable($rows, true, false, true, 'name');
// With named arguments, self-explanatory without checking the signature
renderTable(
$rows,
sortable: true,
paginated: false,
striped: true,
sortColumn: 'name',
);
Once callers can pass arguments by name, renaming a parameter is a breaking change for anyone using named arguments against it — even though it wasn't before 8.0. If you're maintaining a library or a widely-called internal service, treat parameter names in public function signatures with the same care as the function name itself.
Interaction with variadics and positional arguments
Named arguments can't come before positional ones in a single call — createUser(email: '...', 'Amina') is a syntax error, the positional argument has to come first. Variadic parameters (...$rest) can still be filled positionally after all named parameters are satisfied, but you can't target a variadic parameter by name directly since it collects an arbitrary number of values, not one.
function logEvent(string $channel, bool $urgent = false, string ...$tags): void
{
// ...
}
// Named args for the named params, then plain positional values
// flow into the variadic collector
logEvent(channel: 'billing', urgent: true, ...['payment', 'retry']);
A quieter side effect: fewer builder classes
A lot of the "fluent builder" pattern in PHP — Query::make()->where(...)->orderBy(...)->paginate(...) chains — exists partly to work around the lack of named, optional parameters: each method call is really just naming one option. Named arguments don't replace builders where genuine step-by-step composition is the point, but for a function that just takes a bag of independent options, a single call with named arguments is often clearer than a multi-line fluent chain built only to attach labels to values.
Wrapping up
Named arguments are a small addition to the language, but they solve a real and common readability problem: functions with several optional parameters, especially booleans, used to force callers into either memorizing positional order or reading the source every time. Being able to name the parameters you're setting and skip the ones you're not, in any order, makes call sites self-documenting without adding a single line of extra code. If your codebase still has functions with three or more optional boolean parameters called positionally, that's the first place to start using this.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.