Passer un tableau en tant qu'arguments, pas en tant que tableau, en PHP

148

Il me semble que je me souviens qu'en PHP, il existe un moyen de passer un tableau en tant que liste d'arguments pour une fonction, en déréférençant le tableau de func($arg1, $arg2)manière standard . Mais maintenant, je ne sais plus comment faire. Je rappelle la manière de passer par référence, comment "glob" les paramètres entrants ... mais pas comment désenregistrer le tableau dans une liste d'arguments.

C'est peut-être aussi simple que cela func(&$myArgs), mais je suis presque sûr que ce n'est pas ça. Mais, malheureusement, le manuel php.net n'a rien divulgué jusqu'à présent. Non pas que je doive utiliser cette fonctionnalité particulière depuis environ un an.

Robert K
la source

Réponses:

178

http://www.php.net/manual/en/function.call-user-func-array.php

call_user_func_array('func',$myArgs);
vartec
la source
1
J'aurais pu jurer que c'était aussi une non-fonction, comme un caractère préfixe ou quelque chose comme ça. Merci.
Robert K
8
Mais je ne connais pas Python! Je dois être accidentellement psychique ...: D
Robert K
45
La décompression des arguments, comme on l'appelle, sera ajoutée dans PHP 5.6 ( wiki.php.net/rfc/argument_unpacking ). Il utilisera l '«opérateur splat»: «...». Sa syntaxe: $args = [1,2,3]; function(...$args){}
arothuis
4
mais que faire si la fonction que vous souhaitez appeler est une méthode d'instance sur un objet, pas un nom de fonction dans l'espace global?
ahnbizcad
6
@ahnbizcad alors vous devez utiliser a callable, qui utilise le même call_user_func_array, uniquement avec un tableau où le premier élément est l'objet et le second est la méthode. Par exemplecall_user_func_array([$object, 'method'], $myArgs);
SteveB
149

Comme cela a été mentionné , à partir de PHP 5.6+, vous pouvez (devriez!) Utiliser le ...jeton (aka "splat operator", une partie de la fonctionnalité des fonctions variadiques ) pour appeler facilement une fonction avec un tableau d'arguments:

<?php
function variadic($arg1, $arg2)
{
    // Do stuff
    echo $arg1.' '.$arg2;
}

$array = ['Hello', 'World'];

// 'Splat' the $array in the function call
variadic(...$array);

// 'Hello World'

Remarque: les éléments du tableau sont mappés aux arguments par leur position dans le tableau et non par leurs clés.

Selon le commentaire de CarlosCarucce , cette forme de déballage d'arguments est de loin la méthode la plus rapide dans tous les cas. Dans certaines comparaisons, c'est plus de 5 fois plus rapide que call_user_func_array.

De côté

Parce que je pense que c'est vraiment utile (mais pas directement lié à la question): vous pouvez taper le paramètre d'opérateur splat dans votre définition de fonction pour vous assurer que toutes les valeurs passées correspondent à un type spécifique.

(N'oubliez pas que cela DOIT être le dernier paramètre que vous définissez et qu'il regroupe tous les paramètres passés à la fonction dans le tableau.)

C'est idéal pour s'assurer qu'un tableau contient des éléments d'un type spécifique:

<?php

// Define the function...

function variadic($var, SomeClass ...$items)
{
    // $items will be an array of objects of type `SomeClass`
}

// Then you can call...

variadic('Hello', new SomeClass, new SomeClass);

// or even splat both ways

$items = [
    new SomeClass,
    new SomeClass,
];

variadic('Hello', ...$items);
Simonhamp
la source
7
Cela a une grande amélioration des performances call_user_func_array. Donc, si vous utilisez php 5.6+, je recommanderais celui-ci. Voici un test , qui a été cité dans le wiki officiel de php
CarlosCarucce
2
C'est vraiment dommage que ce ne soit pas la réponse claire. Certainement bien mieux
impardonnable1987
81

Notez également que si vous souhaitez appliquer une méthode d'instance à un tableau, vous devez transmettre la fonction comme suit:

call_user_func_array(array($instance, "MethodName"), $myArgs);
Jeff Ober
la source
4
@understack L' $foo->bar()exemple sur la page liée suggère qu'il devrait l'être array($instance, "MethodName").
Paul Calcraft
11
Génial, j'ai utilisé ceci pour éviter de dupliquer les arguments du constructeur dans une classe enfant :)call_user_func_array(array(parent, "__construct"), func_get_args());
Jason
10

Par souci d'exhaustivité, à partir de PHP 5.1, cela fonctionne également:

<?php
function title($title, $name) {
    return sprintf("%s. %s\r\n", $title, $name);
}
$function = new ReflectionFunction('title');
$myArray = array('Dr', 'Phil');
echo $function->invokeArgs($myArray);  // prints "Dr. Phil"
?>

Voir: http://php.net/reflectionfunction.invokeargs

Pour les méthodes, vous utilisez ReflectionMethod :: invokeArgs à la place et passez l'objet comme premier paramètre.

DanMan
la source
C'est en fait ce que je cherchais!
Dejv