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.

Odpowiedzi:


178

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

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

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.


Właśnie tego szukałem!
Dejv
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.