【问题标题】:How can I convert a PHP function's parameter list to an associative array?如何将 PHP 函数的参数列表转换为关联数组?
【发布时间】:2010-11-28 00:21:30
【问题描述】:

我想将函数的参数转换成一个关联数组,其中键等于参数变量名,值等于参数值。

PHP:

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:这将 1) 提供丑陋的 API,以及 2) 需要对调用源进行大量更改。其中许多函数已经存在并且正在被调用。
  • 我真的不明白为什么它会是一个“丑陋”的 API - 对我来说它会更干净,类似于在 Python 中将字典作为参数提供并在 ECMAScript 中提供对象。
  • 它使文档更清晰,并让 PHP 强制每个函数传递正确数量/类型的参数。

标签: php arrays parameters arguments associative


【解决方案1】:

你可以使用compact

function myFunc($a, $b, $c) {
    $params = compact('a', 'b', 'c');
    // ...
}

或者,get_defined_vars() 将为您提供该范围内定义的所有变量的关联数组,这将起作用,但我认为这可能还包括 $_POST$_GET 等...

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

或者,只指定一个参数,它是一个数组:

function myFunc($params) {

}

compact() 似乎最接近你所追求的。

【讨论】:

  • 我不喜欢这个的原因是变量名必须重复。
  • 然后看看get_defined_vars
【解决方案2】:

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)
}

【讨论】:

  • 我应该已经用了很多年了。正确答案。
【解决方案3】:

我赞成@nickf 的回答,但想补充一点,compact() 也是使用 ctor 实例化模型的好方法:

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;
    }
}

只需确保参数与字段的拼写完全相同即可。

【讨论】:

  • 不是我想要的 - 但仍然是一个足够酷的技巧来证明投票的合理性。
【解决方案4】:

按照建议,但未实现:您可以使用Reflection 收集参数名称,然后将它们与值关联:

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:

array(2) {
  ["x"]=>
  int(7)
  ["y"]=>
  int(2)
}
array(1) {
  ["z"]=>
  int(4)
}

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

【讨论】:

    【解决方案5】:

    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');
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-04-02
      • 1970-01-01
      • 2017-09-02
      • 1970-01-01
      • 1970-01-01
      • 2011-05-08
      • 2010-11-28
      • 2018-04-22
      • 1970-01-01
      相关资源
      最近更新 更多