Table of Contents

PHP RFC: Add func_get_args_by_name()

Introduction

This RFC proposes adding a new func_get_args_by_name() function that returns all function arguments with their parameter names preserved as array keys, unlike func_get_args() which returns only positional arguments.

<?php
function greet(string $name, int $age, ...$extra): array {
    return func_get_args_by_name();
}
 
var_dump(greet('Alice', 30, 'foo', 'bar'));
// array(4) {
//   ["name"]=> string(5) "Alice"
//   ["age"]=> int(30)
//   [2]=> string(3) "foo"
//   [3]=> string(3) "bar"
// }
?>

With named arguments becoming widely used since PHP 8.0, this function provides a straightforward way to introspect function calls while preserving argument names.

Motivation

Currently, there is no built-in way to retrieve function arguments with their parameter names. The existing func_get_args() returns only positional values, and func_get_arg() requires knowing the position index. The only way to get named arguments is through reflection, which is verbose:

<?php
function example($a, $b) {
    $reflection = new ReflectionFunction(__FUNCTION__);
    $params = $reflection->getParameters();
    $args = func_get_args();
    $result = [];
    foreach ($params as $i => $param) {
        if (isset($args[$i])) {
            $result[$param->getName()] = $args[$i];
        }
    }
    return $result;
}
?>

The proposed func_get_args_by_name() eliminates this complexity and makes argument introspection straightforward.

Proposal

Add a new func_get_args_by_name() function to PHP. This function:

Key Difference from func_get_args():

When using the spread operator with named arguments, func_get_args_by_name() captures extra named arguments that func_get_args() discards:

<?php
function process(string $name, int $age, ...$extra) {
    return func_get_args();
}
 
var_dump(process(...[
    'age' => 30,
    'name' => 'John',
    'extra' => 'data',
]));
// array(2) {
//   [0]=> string(4) "John"
//   [1]=> int(30)
// }
// 'extra' is missing
 
function process_named(string $name, int $age, ...$extra) {
    return func_get_args_by_name();
}
 
var_dump(process_named(...[
    'age' => 30,
    'name' => 'John',
    'extra' => 'data',
]));
// array(3) {
//   ["name"]=> string(4) "John"
//   ["age"]=> int(30)
//   ["extra"]=> string(4) "data"
// }
?>

Backward Incompatible Changes

This RFC introduces a new function without modifying existing functionality. Userland code declaring a function in the global namespace using this name would not work anymore, but a quick search on GitHub with the proposed function name revealed no result.

Proposed PHP Version

PHP 8.6 (next minor version)

Voting Choices

This is a simple yes/no vote requiring a 2/3 majority.

Add func_get_args_by_name() to PHP 8.6?
Real name Yes No Abstain
Final result: 0 0 0
This poll has been closed.

Vote will start on [TBD] and end on [TBD].

References