Przekazywanie tablicy jako argumentów, a nie tablicy, w PHP

148

Wydaje mi się, że pamiętam, że w PHP istnieje sposób na przekazanie tablicy jako listy argumentów funkcji, dereferencjonując tablicę w standardowy func($arg1, $arg2)sposób. Ale teraz nie wiem, jak to zrobić. Przypominam sobie sposób przekazywania przez odniesienie, „globowanie” przychodzących parametrów ... ale nie sposób usuwania tablicy do listy argumentów.

Może to być tak proste, jak func(&$myArgs), ale jestem pewien, że to nie jest to. Niestety, jak dotąd podręcznik php.net niczego nie ujawnił. Nie, żebym musiał używać tej konkretnej funkcji przez ostatni rok.

Robert K.
źródło

Odpowiedzi:

178

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

call_user_func_array('func',$myArgs);
vartec
źródło
1
Mógłbym przysiąc, że to również nie jest funkcja, jak znak przedrostka lub coś w tym rodzaju. Dzięki.
Robert K
8
Ale ja nie znam Pythona! Muszę być przypadkowo psychiczny ...: D
Robert K
45
Rozpakowywanie argumentów, jak to się nazywa, zostanie dodane w PHP 5.6 ( wiki.php.net/rfc/argument_unpacking ). Użyje „operatora splat”: „...”. Jego składnia: $args = [1,2,3]; function(...$args){}
arothuis
4
ale co, jeśli funkcja, którą chcesz wywołać, jest metodą instancji obiektu, a nie nazwą funkcji w przestrzeni globalnej?
ahnbizcad
6
@ahnbizcad to powinieneś użyć a callable, który używa tego samego call_user_func_array, tylko z tablicą, w której pierwszy element to obiekt, a drugi to metoda. Na przykładcall_user_func_array([$object, 'method'], $myArgs);
SteveB
149

Jak już wspomniano , od PHP 5.6+ możesz (powinieneś!) Użyć ...tokena (znanego również jako "operator splat", część funkcjonalności funkcji wariadycznych ), aby łatwo wywołać funkcję z tablicą argumentów:

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

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

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

// 'Hello World'

Uwaga: elementy tablicy są mapowane na argumenty na podstawie ich pozycji w tablicy, a nie kluczy.

Zgodnie z komentarzem CarlosCarucce , ta forma rozpakowywania argumentów jest zdecydowanie najszybszą metodą we wszystkich przypadkach. W niektórych porównaniach jest ponad 5 razy szybszy niż call_user_func_array.

Na bok

Ponieważ myślę, że jest to naprawdę przydatne (choć nie jest bezpośrednio związane z pytaniem): możesz wskazać parametr operatora splat w definicji funkcji, aby upewnić się, że wszystkie przekazane wartości pasują do określonego typu.

(Pamiętaj tylko, że robiąc to MUSI to być ostatni zdefiniowany parametr i że wszystkie parametry przekazane do funkcji zostaną umieszczone w tablicy).

Jest to świetne do upewnienia się, że tablica zawiera elementy określonego typu:

<?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
źródło
7
Ma to dużą poprawę wydajności w porównaniu z call_user_func_array. Więc jeśli używasz php 5.6+, polecam ten. Oto test , który był cytowany na oficjalnej wiki php
CarlosCarucce
2
Szkoda, że ​​to nie jest zaznaczona odpowiedź. Zdecydowanie lepiej
przebaczenia 1987
81

Pamiętaj również, że jeśli chcesz zastosować metodę instancji do tablicy, musisz przekazać funkcję jako:

call_user_func_array(array($instance, "MethodName"), $myArgs);
Jeff Ober
źródło
4
@understack $foo->bar()Przykład na połączonej stronie sugeruje, że tak powinno być array($instance, "MethodName").
Paul Calcraft
11
Świetnie, użyłem tego, aby uniknąć powielania argumentów konstruktora w klasie dziecięcej :)call_user_func_array(array(parent, "__construct"), func_get_args());
Jason
10

Ze względu na kompletność, od PHP 5.1 to również działa:

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

Widzieć: http://php.net/reflectionfunction.invokeargs

W przypadku metod zamiast tego używasz ReflectionMethod :: invokeArgs i przekazujesz obiekt jako pierwszy parametr.

DanMan
źródło
Właśnie tego szukałem!
Dejv