如何将PHP函数的参数列表转换为关联数组?

9
我希望将函数参数转换为一个关联数组,其中键等于参数变量名,值等于参数值。请参考以下PHP代码示例:
```php function example($arg1, $arg2) { $args = array( 'arg1' => $arg1, 'arg2' => $arg2 ); // code here } ```
function my_function($a, $b, $c) {

    // <--- magic goes here to create the $params array

    var_dump($params['a'] === $a); // Should result in bool(true)
    var_dump($params['b'] === $b); // Should result in bool(true)
    var_dump($params['c'] === $c); // Should result in bool(true)
}

我该如何做到这一点?


你为什么不能定义初始函数来接受一个数组作为第一个参数并传入一个数组呢? - meder omuraliev
1
meder:这将会1)提供一个丑陋的API,2)需要对调用源进行大量更改。许多这些函数已经存在并正在被调用。 - Fragsworth
1
我并不认为这会是一个“丑陋”的API - 对我来说,它会更加简洁,并类似于在Python中将字典作为参数传递和在ECMAScript中传递对象。 - meder omuraliev
2
它使文档更清晰,并让PHP强制确保每个函数传递了正确数量/类型的参数。 - nickf
5个回答

12
你可以使用compact来实现这个功能。
function myFunc($a, $b, $c) {
    $params = compact('a', 'b', 'c');
    // ...
}

或者,get_defined_vars() 将会给你一个关联数组,包含该范围内定义的所有变量,这个方法也可以使用,但我认为它可能也会包括 $_POST$_GET等。

否则,你可以使用func_get_args获取传递给函数的所有参数列表。然而,这个列表不是关联的,因为只有传递的数据(也就是说没有变量名)。这个方法也允许在函数中使用任意数量的参数。

或者,只需指定一个参数,即一个数组:

function myFunc($params) {

}

compact() 看起来是最符合你要求的。


我不喜欢这个的原因是变量名必须要重复。 - Fragsworth
1
看看get_defined_vars吧。 - nickf

10

get_defined_vars() 是你需要的函数,如果在其被调用之前没有定义其他变量(你可以通过将其放在函数内部的第一件事来确保这一点)。

function my_function($a, $b, $c) {

    $params = get_defined_vars(); // <--- create the $params array

    var_dump($params['a'] === $a); // results in bool(true)
    var_dump($params['b'] === $b); // results in bool(true)
    var_dump($params['c'] === $c); // results in bool(true)
}

我应该多年前就开始使用这个了。这才是正确的答案。 - user3751385
这也适用于将最后一个参数展开的情况。 - mickmackusa

4
我赞同@nickf的回答,但我想补充一下,使用compact()也是一个通过构造函数实例化模型的好方法。
class User {
    public $email;
    public $password;
    public $firstName;
    public $lastName;

    public function __construct ( $email, $password, $firstName, $lastName )
    {
        foreach ( compact( array_keys( (array)$this )) as $k => $v )
            $this->$k = $v;
    }
}

请确保参数与字段的拼写完全相同。


不是我正在寻找的东西 - 但仍然是一个很酷的技巧,值得一个点赞。 - user3751385

1
正如已经提到但没有实现的那样:您可以使用反射来收集参数名称,然后将其与值关联起来。
function args_to_assoc_array($function, $args) {                                 
    if (false === strpos($function, '::')) {                                     
        $reflection = new ReflectionFunction($function);                         
    } else {                                                                     
        $reflection = new ReflectionMethod(...explode('::', $function));         
    }                                                                            
    $assoc = [];                                                                 
    foreach ($reflection->getParameters() as $i => $parameter) {                 
        $assoc[$parameter->getName()] = $args[$i];                               
    }                                                                            
    return $assoc;                                                               
}                                                                                

然后您可以以相同的方式调用它,无论是在函数还是方法中:
function f($x, $y) { return args_to_assoc_array(__METHOD__, func_get_args()); }
class A {                                                                     
    function m($z) { return args_to_assoc_array(__METHOD__, func_get_args()); }
}                                                                             
var_dump(f(7, 2), (new A)->m(4));                                             

which outputs:

的英译中,保留html,不要解释。
array(2) {
  ["x"]=>
  int(7)
  ["y"]=>
  int(2)
}
array(1) {
  ["z"]=>
  int(4)
}

我没有计时,但我强烈怀疑这比使用compact要慢得多。


0

PHP 8+ 命名参数

class User
{
    private string $email;
    private string $password;
    public string $firstName;
    protected string $lastName;

    public function __construct(...$arguments)
    {

        setterObject($this, ...$arguments);

        var_dump('email: ' . $this->email);
        var_dump('password: ' . $this->password);
        var_dump($this->firstName);
        var_dump($this->lastName);


    }
}

new User(email:'xxxxx@email.com', password: '#@some@password@_', firstName: 'firstName', lastName: 'lastName');

function setterObject(object $obj, mixed ...$arguments)
{
    $args = get_defined_vars()['arguments'];
    //just named arguments
    if (count(array_filter(array_keys($args), 'is_string')) ===count($args) ) {
        array_map(function ($prop) use ($obj,$args ) {
            $prop->setAccessible(true);
            if(!is_null($args[$prop->getName()])) {
                $prop->setValue($obj, $args[$prop->getName()]);
            }
        }, (new ReflectionObject($obj))->getProperties());
    }else{
        throw new Exception('the object was not initialized');
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接