Übergeben eines Arrays als Argumente, nicht als Array, in PHP

147

Ich scheine mich zu erinnern, dass es in PHP eine Möglichkeit gibt, ein Array als Liste von Argumenten für eine Funktion zu übergeben und das Array auf die Standardweise func($arg1, $arg2)zu dereferenzieren . Aber jetzt weiß ich nicht, wie es geht. Ich erinnere mich an die Art der Referenzübergabe, wie man eingehende Parameter "globalisiert" ... aber nicht, wie man das Array in eine Liste von Argumenten auflistet.

Es mag so einfach sein wie func(&$myArgs), aber ich bin mir ziemlich sicher, dass es nicht so ist. Leider hat das php.net-Handbuch bisher nichts preisgegeben. Nicht, dass ich diese spezielle Funktion im letzten Jahr oder so verwenden musste.

Robert K.
quelle

Antworten:

178

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

call_user_func_array('func',$myArgs);
vartec
quelle
1
Ich hätte schwören können, dass es auch eine Nichtfunktion war, wie ein Präfixzeichen oder so. Vielen Dank.
Robert K
8
Aber ich kenne Python nicht! Ich muss versehentlich psychisch sein ...: D
Robert K
45
Das so genannte Entpacken von Argumenten wird in PHP 5.6 ( wiki.php.net/rfc/argument_unpacking ) hinzugefügt . Es wird der 'Splat-Operator' verwendet: '...'. Seine Syntax: $args = [1,2,3]; function(...$args){}
Arothuis
4
Was aber, wenn die Funktion, die Sie aufrufen möchten, eine Instanzmethode für ein Objekt ist, kein Funktionsname im globalen Raum?
Ahnbizcad
6
@ahnbizcad dann sollten Sie ein callableverwenden, das dasselbe verwendet call_user_func_array, nur mit Array, wobei das erste Element das Objekt und das zweite die Methode ist. Zum Beispielcall_user_func_array([$object, 'method'], $myArgs);
SteveB
148

Wie bereits erwähnt , können (sollten!) Ab PHP ...5.6+ das Token (auch bekannt als "Splat-Operator", Teil der Funktionalität für verschiedene Funktionen) verwendet werden, um eine Funktion mit einer Reihe von Argumenten einfach aufzurufen:

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

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

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

// 'Hello World'

Hinweis: Array-Elemente werden anhand ihrer Position im Array und nicht anhand ihrer Schlüssel Argumenten zugeordnet .

Wie pro CarlosCarucce Kommentar , diese Form der Argumentation auspacken ist bei weitem die schnellste Methode in allen Fällen. In einigen Vergleichen ist es über 5x schneller als call_user_func_array.

Beiseite

Weil ich denke, dass dies wirklich nützlich ist (obwohl es nicht direkt mit der Frage zusammenhängt): Sie können den Splat-Operator-Parameter in Ihrer Funktionsdefinition tippen , um sicherzustellen, dass alle übergebenen Werte einem bestimmten Typ entsprechen.

(Denken Sie daran, dass dies der letzte von Ihnen definierte Parameter sein MUSS und dass alle an die Funktion übergebenen Parameter im Array gebündelt werden.)

Dies ist ideal, um sicherzustellen, dass ein Array Elemente eines bestimmten Typs enthält:

<?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
quelle
7
Dies hat eine große Leistungsverbesserung gegenüber call_user_func_array. Also, wenn Sie PHP 5.6+ verwenden, würde ich dieses empfehlen. Hier ist ein Test , der im offiziellen PHP-Wiki
CarlosCarucce
2
Es ist wirklich bedauerlich, dass dies nicht die markierte Antwort ist. Auf jeden Fall viel besser
unverzeihlich1987
81

Beachten Sie außerdem, dass Sie die Funktion wie folgt übergeben müssen, wenn Sie eine Instanzmethode auf ein Array anwenden möchten:

call_user_func_array(array($instance, "MethodName"), $myArgs);
Jeff Ober
quelle
4
@understack Das $foo->bar()Beispiel auf der verlinkten Seite legt nahe, dass dies der Fall sein sollte array($instance, "MethodName").
Paul Calcraft
11
Genial, ich habe dies verwendet, um zu vermeiden, dass Konstruktorargumente in einer untergeordneten Klasse dupliziert werden :)call_user_func_array(array(parent, "__construct"), func_get_args());
Jason
10

Der Vollständigkeit halber funktioniert dies ab PHP 5.1 auch:

<?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"
?>

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

Für Methoden verwenden Sie stattdessen ReflectionMethod :: invokeArgs und übergeben das Objekt als ersten Parameter.

DanMan
quelle
Das ist genau das, wonach ich gesucht habe!
Dejv