Comment passer un nombre variable d'arguments à une fonction PHP

115

J'ai une fonction PHP qui prend un nombre variable d'arguments (en utilisant func_num_args()et func_get_args()), mais le nombre d'arguments que je veux transmettre à la fonction dépend de la longueur d'un tableau. Existe-t-il un moyen d' appeler une fonction PHP avec un nombre variable d'arguments?

nohat
la source
1
Vérifiez ma réponse pour en savoir plus sur un opérateur splat dans le nouveau php5.6: stackoverflow.com/a/23163963/1090562
Salvador Dali

Réponses:

132

Si vous avez vos arguments dans un tableau, vous pourriez être intéressé par la call_user_func_arrayfonction.

Si le nombre d'arguments que vous souhaitez transmettre dépend de la longueur d'un tableau, cela signifie probablement que vous pouvez les regrouper eux-mêmes dans un tableau - et utiliser celui-ci pour le deuxième paramètre de call_user_func_array.

Les éléments de ce tableau que vous passez seront alors reçus par votre fonction en tant que paramètres distincts.


Par exemple, si vous avez cette fonction:

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

Vous pouvez regrouper vos paramètres dans un tableau, comme ceci:

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

Et, ensuite, appelez la fonction:

call_user_func_array('test', $params);

Ce code sera la sortie:

int 3

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

c'est-à-dire 3 paramètres; exactement comme si la fonction était appelée de cette façon:

test(10, 'glop', 'test');
Pascal MARTIN
la source
1
Oui merci. call_user_func_array () est exactement la fonction que je recherchais.
nohat le
Est-il possible d'utiliser call_user_func_array () avec un appel de méthode objet?
nohat le
6
@nohat: de rien :-) ;; à propos de l'utilisation d'une méthode d'un objet: oui, vous pouvez, en utilisant quelque chose comme array ($ obj, 'methodName') comme premier paramètre ;; en fait, vous pouvez transmettre n'importe quel «rappel» à cette fonction. Pour plus d'informations sur les callbacks, voir php.net/callback#language.types.callback
Pascal MARTIN
58

C'est désormais possible avec PHP 5.6.x , en utilisant l'opérateur ... (également connu sous le nom d'opérateur splat dans certaines langues):

Exemple:

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' ) );
JCM
la source
1
La liste des arguments de variables typées est une fonctionnalité introduite dans PHP 7 .
Daniele Orlando
46

Dans un nouveau Php 5.6 , vous pouvez utiliser ... operatorau lieu d'utiliser func_get_args().

Ainsi, en utilisant ceci, vous pouvez obtenir tous les paramètres que vous passez:

function manyVars(...$params) {
   var_dump($params);
}
Salvador Dali
la source
3
Plus d'infos ici: php.net/manual/en
...
À partir du lien @fracz, OP tente de créer une «fonction variadique».
Nathan Arthur
40

Depuis PHP 5.6 , une liste d'arguments variables peut être spécifiée avec l' ...opérateur.

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

Comme vous pouvez le voir, l' ...opérateur collecte la liste variable des arguments dans un tableau.

Si vous devez passer les arguments de variable à une autre fonction, le ...peut toujours vous aider.

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

Depuis PHP 7 , la liste des variables des arguments peut être forcée à être toutes du même type aussi.

function do_something($first, int ...$all_the_others) { /**/ }
Daniele Orlando
la source
11

Pour ceux qui recherchent un moyen de le faire avec $object->method:

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

J'ai réussi avec cela dans une fonction de construction qui appelle une variable method_name avec des paramètres variables.

Danilo
la source
2
Vous pouvez également utiliser$object->method_name(...$array);
Yoann Kergall
Pour aller plus loin, si vous voulez passer par référence, utilisez$object->method_name(&...$args);
Fabien Haddadi
4

Vous pouvez simplement l'appeler.

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

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

Production:

Array ([0] => bla) Array ([0] => bla [1] => bla)

Donnie C
la source
Si je comprends bien l'OP, le problème n'est pas de recevoir les paramètres, mais d' appeler la fonction avec un nombre variable de paramètres.
Pascal MARTIN
1
Je n'ai donc pas bien compris le PO. Un tableau serait donc certainement la voie à suivre. Là encore, il pourrait simplement passer le tableau directement dans test (), non?
Donnie C
1
Passer un tableau pourrait être une solution aussi, en effet - Si j'ai bien compris ^^
Pascal MARTIN
1
Ancienne question mais pour info, un tableau fonctionne bien mais le fait de passer des arguments réels vous permet d'utiliser les valeurs par défaut de PHP pour les arguments nuls, ce qui évite beaucoup de vilaines vérifications pour voir si le tableau contient des valeurs particulières.
Endophage
1

Une vieille question, je sais, cependant, aucune des réponses ici ne fait vraiment un bon travail de répondre simplement à la question.

Je viens de jouer avec php et la solution ressemble à ceci:

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

Cette fonction peut faire deux choses:

S'il est appelé avec uniquement le paramètre requis: myFunction("Hi") il affichera "Salut par défaut"

Mais s'il est appelé avec le paramètre optionnel: myFunction("Hi","me") il affichera "Salut moi";

J'espère que cela aidera quiconque recherchera cela plus tard.

Alex
la source
2
Vous n'avez pas compris la question. OP posait des questions sur les arguments qu'il n'avait pas à définir explicitement dans la signature de la fonction - mais il peut toujours passer des valeurs comme arguments à la fonction. Par exemple, la signature de la fonction n'a aucun argument défini (optionnel ou non), mais quand il le demande, OP peut envoyer 45 valeurs différentes comme arguments à la fonction.
a20
0

Voici une solution utilisant la méthode magique __invoke

(Disponible depuis 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){

    }
}

De l'intérieur de la même classe:

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

À partir d'une instance d'un objet:

$obj = new Foo;
$obj('methodName', ['arg1', 'arg2', 'arg3'])
Dieter Gribnitz
la source
Ceci est essentiellement utilisé call_user_func_arraycomme indiqué par la réponse la plus votée en 2009. Peut-être qu'il est utile d'envelopper un supplément __invoke- mais je ne le vois pas.
a20