Como passar um número variável de argumentos para uma função PHP


115

Eu tenho uma função PHP que leva um número variável de argumentos (usando func_num_args()e func_get_args()), mas o número de argumentos que desejo passar a função depende do comprimento de uma matriz. Existe uma maneira de chamar uma função PHP com um número variável de argumentos?


1
Verifique minha resposta para aprender sobre um operador splat no novo php5.6: stackoverflow.com/a/23163963/1090562
Salvador Dali

Respostas:


132

Se você tem seus argumentos em uma matriz, pode se interessar pela call_user_func_arrayfunção.

Se o número de argumentos que você deseja passar depende do comprimento de um array, isso provavelmente significa que você pode empacotá-los em um array - e usar esse como o segundo parâmetro de call_user_func_array.

Os elementos desse array que você passar serão recebidos por sua função como parâmetros distintos.


Por exemplo, se você tem esta função:

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

Você pode empacotar seus parâmetros em uma matriz, assim:

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

E, então, chame a função:

call_user_func_array('test', $params);

Este código terá como resultado:

int 3

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

ou seja, 3 parâmetros; exatamente como iof a função era chamada desta forma:

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

1
Sim obrigada. call_user_func_array () é exatamente a função que eu estava procurando.
nohat

É possível usar call_user_func_array () com uma chamada de método de objeto?
nohat

6
@nohat: de nada :-) ;; sobre usar um método de um objeto: sim, você pode, usando algo como array ($ obj, 'methodName') como primeiro parâmetro ;; na verdade, você pode passar qualquer "retorno de chamada" que desejar para essa função. Para obter mais informações sobre callbacks, consulte php.net/callback#language.types.callback
Pascal MARTIN

58

Isso agora é possível com PHP 5.6.x , usando o operador ... (também conhecido como operador splat em algumas linguagens):

Exemplo:

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
A lista de argumentos de variáveis digitadas é um recurso introduzido no PHP 7 .
Daniele Orlando

46

Em um novo Php 5.6 , você pode usar em ... operatorvez de usar func_get_args().

Então, usando isso, você pode obter todos os parâmetros que passar:

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

3
Mais informações aqui: php.net/manual/en/…
fracz

No link @fracz, OP está tentando criar uma "função variada".
Nathan Arthur

40

Desde o PHP 5.6 , uma lista de argumentos variáveis ​​pode ser especificada com o ...operador.

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

Como você pode ver, o ...operador coleta a lista de variáveis ​​de argumentos em uma matriz.

Se você precisar passar os argumentos variáveis ​​para outra função, o ...ainda pode ajudá-lo.

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

Desde o PHP 7 , a lista de argumentos variáveis ​​pode ser forçada a ser todos do mesmo tipo também.

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

11

Para quem procura uma maneira de fazer isso com $object->method:

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

Tive sucesso com isso em uma função de construção que chama uma variável method_name com parâmetros variáveis.


2
Você também pode usar$object->method_name(...$array);
Yoann Kergall

Indo mais longe, se você quiser passar por referência, use$object->method_name(&...$args);
Fabien Haddadi

4

Você pode simplesmente chamá-lo.

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

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

Resultado:

Matriz ([0] => blá) Matriz ([0] => blá [1] => blá)


Se entendi o OP corretamente, o problema não é receber os parâmetros, mas sim chamar a função com um número variável de parâmetros.
Pascal MARTIN,

1
Não entendi o OP corretamente, então. Uma matriz definitivamente seria o caminho a percorrer, então. Então, novamente, ele poderia simplesmente passar o array diretamente em test (), não?
Donnie C

1
Passar um array também pode ser uma solução - Se bem entendi ^^
Pascal MARTIN

1
Uma questão antiga, mas fyi, um array funciona bem, mas passar argumentos reais permite que você use os valores padrão do PHP para argumentos nulos, o que evita muitas verificações feias para ver se o array contém valores particulares.
Endophage


1

Uma velha pergunta, eu sei, no entanto, nenhuma das respostas aqui realmente faz um bom trabalho de simplesmente responder à pergunta.

Acabei de brincar com php e a solução é esta:

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

Essa função pode fazer duas coisas:

Se for chamado apenas com o parâmetro necessário: myFunction("Hi") Irá imprimir "Hi default"

Mas se for chamado com o parâmetro opcional: myFunction("Hi","me") Vai imprimir "Hi me";

Espero que isso ajude quem está procurando por isso no futuro.


2
Você não conseguiu entender a pergunta. OP estava perguntando sobre argumentos que ele não precisava definir explicitamente na assinatura da função - mas ele ainda pode passar valores como argumentos para a função. Por exemplo, a assinatura da função não tem nenhum argumento definido (opcional ou não), mas quando requerido, OP pode enviar 45 valores diferentes como argumentos para a função.
a20,

0

Aqui está uma solução usando o método mágico __invoke

(Disponível desde o 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){

    }
}

Dentro da mesma classe:

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

De uma instância de um objeto:

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

Basicamente, isso é usado call_user_func_arraycomo declarado pela resposta mais votada em 2009. Talvez haja um ponto em colocar um extra em __invoketorno disso - mas eu não vejo isso.
a20 de
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.