Как передать переменное количество аргументов функции PHP


115

У меня есть функция PHP, которая принимает переменное количество аргументов (с использованием func_num_args()и func_get_args()), но количество аргументов, которые я хочу передать функции, зависит от длины массива. Есть ли способ вызвать функцию PHP с переменным количеством аргументов?


1
Посмотрите мой ответ, чтобы узнать об операторе splat в новом php5.6: stackoverflow.com/a/23163963/1090562
Сальвадор Дали,

Ответы:


132

Если у вас есть аргументы в виде массива, call_user_func_arrayфункция может вас заинтересовать .

Если количество аргументов, которые вы хотите передать, зависит от длины массива, это, вероятно, означает, что вы можете сами упаковать их в массив - и использовать его для второго параметра call_user_func_array.

Элементы этого массива, которые вы передаете, будут затем получены вашей функцией как отдельные параметры.


Например, если у вас есть эта функция:

function test() {
  var_dump(func_num_args());
  var_dump(func_get_args());
}

Вы можете упаковать свои параметры в массив, например:

$params = array(
  10,
  'glop',
  'test',
);

А затем вызовите функцию:

call_user_func_array('test', $params);

Этот код будет выводить:

int 3

array
  0 => int 10
  1 => string 'glop' (length=4)
  2 => string 'test' (length=4)

т.е. 3 параметра; точно так же, как и функция вызывалась так:

test(10, 'glop', 'test');

1
Да спасибо. call_user_func_array () - это именно та функция, которую я искал.
nohat

Можно ли использовать call_user_func_array () с вызовом метода объекта?
nohat

6
@nohat: пожалуйста :-) ;; об использовании метода объекта: да, вы можете, используя что-то вроде array ($ obj, 'methodName') в качестве первого параметра ;; фактически, вы можете передать любой «обратный вызов» этой функции. Для получения дополнительной информации об обратных вызовах
Паскаль МАРТИН,

58

Теперь это возможно в PHP 5.6.x , используя оператор ... (также известный как оператор splat в некоторых языках):

Пример:

function addDateIntervalsToDateTime( DateTime $dt, DateInterval ...$intervals )
{
    foreach ( $intervals as $interval ) {
        $dt->add( $interval );
    }
    return $dt;
}

addDateIntervaslToDateTime( new DateTime, new DateInterval( 'P1D' ), 
        new DateInterval( 'P4D' ), new DateInterval( 'P10D' ) );

1
Список типизированных переменных аргументов - это функция, представленная в PHP 7 .
Даниэле Орландо

46

В новом Php 5.6 вы можете использовать ... operatorвместо использования func_get_args().

Итак, используя это, вы можете получить все передаваемые параметры:

function manyVars(...$params) {
   var_dump($params);
}

3
Подробнее здесь: php.net/manual/en/…
fracz

По ссылке @fracz OP пытается создать «вариативную функцию».
Натан Артур

40

Начиная с PHP 5.6 , список переменных аргументов можно указать с помощью ...оператора.

function do_something($first, ...$all_the_others)
{
    var_dump($first);
    var_dump($all_the_others);
}

do_something('this goes in first', 2, 3, 4, 5);

#> string(18) "this goes in first"
#>
#> array(4) {
#>   [0]=>
#>   int(2)
#>   [1]=>
#>   int(3)
#>   [2]=>
#>   int(4)
#>   [3]=>
#>   int(5)
#> }

Как видите, ...оператор собирает список переменных аргументов в массив.

Если вам нужно передать переменные аргументы другой функции, это ...все равно может вам помочь.

function do_something($first, ...$all_the_others)
{
    do_something_else($first, ...$all_the_others);
    // Which is translated to:
    // do_something_else('this goes in first', 2, 3, 4, 5);
}

Поскольку PHP 7 , переменная список аргументов может быть вынужден быть все одного и того же типа тоже.

function do_something($first, int ...$all_the_others) { /**/ }

11

Для тех, кто ищет способ сделать это с помощью $object->method:

call_user_func_array(array($object, 'method_name'), $array);

Мне удалось это сделать в функции конструкции, которая вызывает переменную method_name с параметрами переменных.


2
Вы также можете использовать$object->method_name(...$array);
Йоанн Кергалл

Идя дальше, если вы хотите пройти по ссылке, используйте$object->method_name(&...$args);
Фабьен Хаддади

4

Вы можете просто назвать это.

function test(){        
     print_r(func_get_args());
}

test("blah");
test("blah","blah");

Вывод:

Массив ([0] => бла) Массив ([0] => бла [1] => бла)


Если я правильно понимаю OP, проблема не в получении параметров, а в вызове функции с переменным количеством параметров.
Паскаль МАРТИН

1
Тогда я неправильно понял OP. Тогда массив определенно будет подходящим вариантом. С другой стороны, он мог бы просто передать массив непосредственно в test (), не так ли?
Donnie C

1
Передача массива тоже может быть решением - Если я правильно понял ^^
Паскаль МАРТИН

1
Старый вопрос, но, к сведению, массив работает нормально, но передача фактических аргументов позволяет использовать значения PHP по умолчанию для нулевых аргументов, что избавляет от множества уродливых проверок, чтобы увидеть, содержит ли массив определенные значения.
Endophage

2

Я удивлен, что здесь никто не упомянул просто передачу и извлечение массива. Например:

function add($arr){
    extract($arr, EXTR_REFS);
    return $one+$two;
}
$one = 1;
$two = 2;
echo add(compact('one', 'two')); // 3

Конечно, это не обеспечивает проверку аргументов . Для этого любой может использовать мою функцию ожидания: https://gist.github.com/iautomation/8063fc78e9508ed427d5


1

Старый вопрос, я знаю, однако, что ни один из ответов здесь не дает простого ответа на этот вопрос.

Я просто поигрался с php, и решение выглядит так:

function myFunction($requiredArgument, $optionalArgument = "default"){
   echo $requiredArgument . $optionalArgument;
}

Эта функция может делать две вещи:

Если он вызывается только с обязательным параметром: myFunction("Hi") он напечатает "Hi default"

Но если он вызывается с необязательным параметром: myFunction("Hi","me") он напечатает «Привет мне»;

Я надеюсь, что это поможет всем, кто ищет это в будущем.


2
Вы не поняли вопроса. OP спрашивал об аргументах, которые ему не нужно было явно определять в сигнатуре функции, но он все еще может передавать значения в качестве аргументов функции. Например, функция подписи не имеет каких - либо аргументов определяется ( по желанию или нет), но , когда он требует, OP может послать 45 различных значений в качестве аргументов функции.
a20 07

0

Вот решение с использованием магического метода __invoke

(Доступно с php 5.3)

class Foo {
    public function __invoke($method=null, $args=[]){
        if($method){
            return call_user_func_array([$this, $method], $args);
        }
        return false;
    }

    public function methodName($arg1, $arg2, $arg3){

    }
}

Изнутри того же класса:

$this('methodName', ['arg1', 'arg2', 'arg3']);

Из экземпляра объекта:

$obj = new Foo;
$obj('methodName', ['arg1', 'arg2', 'arg3'])

Это в основном использование, call_user_func_arrayкак указано в ответе, получившем наибольшее количество голосов в 2009 году. Может быть, есть смысл обернуть __invokeвокруг него лишнее, но я этого не вижу.
a20 07
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.