Как я могу преобразовать список параметров функции PHP в ассоциативный массив? - PullRequest
9 голосов
/ 14 сентября 2009

Я хочу преобразовать аргументы функции в ассоциативный массив , ключи которого равны именам переменных параметров, а значения равны значениям параметров.

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

Как я могу это сделать?

Ответы [ 4 ]

12 голосов
/ 14 сентября 2009

Вы можете сделать это, используя compact:

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

Или get_defined_vars() даст вам ассоциативный массив всех переменных, определенных в этой области, который будет работать, но я думаю, что это может также включать $_POST, $_GET и т. Д. ..

В противном случае вы можете использовать func_get_args, чтобы получить список всех аргументов, переданных функции. Это не ассоциативно, хотя, поскольку передаются только данные (то есть имена переменных отсутствуют). Это также позволяет вам иметь любое количество аргументов в вашей функции.

Или просто укажите один аргумент, который является массивом:

function myFunc($params) {

}

compact() кажется наиболее близким к тому, что вы ищете.

9 голосов
/ 14 сентября 2009

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)
}
4 голосов
/ 10 апреля 2014

Я одобрил ответ @ 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;
    }
}

Просто убедитесь, что параметры имеют то же самое написание, что и поля.

1 голос
/ 12 декабря 2018

Как было предложено, но не реализовано: вы можете использовать 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));                                             

который выводит :

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

Я не рассчитывал это, но я сильно подозреваю, что это намного медленнее, чем использование compact.

...