Passare una matrice come Argomenti, non una matrice, in PHP


148

Mi sembra di ricordare che in PHP esiste un modo per passare un array come un elenco di argomenti per una funzione, dereferenziando l'array nel func($arg1, $arg2)modo standard . Ma ora mi sono perso su come farlo. Ricordo il modo di passare per riferimento, come "glob" i parametri in arrivo ... ma non come de-list l'array in un elenco di argomenti.

Potrebbe essere semplice func(&$myArgs), ma sono abbastanza sicuro che non lo sia. Ma, purtroppo, il manuale di php.net non ha divulgato nulla finora. Non che abbia dovuto usare questa particolare funzione per l'ultimo anno o giù di lì.

Risposte:


178

1
Avrei potuto giurare che era anche una non funzione, come un carattere prefisso o qualcosa del genere. Grazie.
Robert K,

8
Ma non conosco Python! Devo essere accidentalmente sensitivo ...: D
Robert K,

45
La decompressione degli argomenti, come viene chiamata, verrà aggiunta in PHP 5.6 ( wiki.php.net/rfc/argument_unpacking ). Userà l '"operatore splat": "...". La sua sintassi: $args = [1,2,3]; function(...$args){}
arothuis

4
ma cosa succede se la funzione che si desidera chiamare è un metodo di istanza su un oggetto, non un nome di funzione nello spazio globale?
ahnbizcad,

6
@ahnbizcad allora dovresti usare a callable, che usa lo stesso call_user_func_array, solo con array in cui il primo elemento è l'oggetto, e il secondo è il metodo. Ad esempiocall_user_func_array([$object, 'method'], $myArgs);
SteveB,

149

Come è stato menzionato , a partire da PHP 5.6+ puoi (dovresti!) Usare il ...token (aka "operatore splat", parte della funzionalità delle funzioni variadiche ) per chiamare facilmente una funzione con una serie di argomenti:

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

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

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

// 'Hello World'

Nota: gli elementi dell'array sono associati agli argomenti in base alla loro posizione nell'array, non alle loro chiavi.

Secondo il commento di CarlosCarucce , questa forma di disimballaggio è il metodo più veloce in assoluto in tutti i casi. In alcuni confronti, è oltre 5 volte più veloce di call_user_func_array.

A parte

Perché penso che questo sia davvero utile (anche se non direttamente correlato alla domanda): puoi digitare-suggerire il parametro dell'operatore splat nella definizione della tua funzione per assicurarti che tutti i valori passati corrispondano a un tipo specifico.

(Ricorda solo che in questo modo DEVE essere l' ultimo parametro che definisci e che raggruppa tutti i parametri passati alla funzione nell'array.)

Questo è ottimo per assicurarsi che un array contenga elementi di un tipo specifico:

<?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
Questo ha migliorato notevolmente le prestazioni call_user_func_array. Quindi, se stai usando php 5.6+, consiglierei questo. Ecco un test , che è stato citato nel wiki ufficiale del php
CarlosCarucce il

2
È davvero un peccato che questa non sia la risposta marcata. Sicuramente molto meglio
unforgiven1987

81

Si noti inoltre che se si desidera applicare un metodo di istanza a un array, è necessario passare la funzione come:

call_user_func_array(array($instance, "MethodName"), $myArgs);

4
@understack L' $foo->bar()esempio nella pagina collegata suggerisce che dovrebbe essere array($instance, "MethodName").
Paul Calcraft,

11
Fantastico, l'ho usato per evitare di duplicare gli argomenti del costruttore in una classe figlio :)call_user_func_array(array(parent, "__construct"), func_get_args());
Jason,

10

Per completezza, a partire da PHP 5.1 funziona anche questo:

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

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

Per i metodi si utilizza invece ReflectionMethod :: invokeArgs e si passa l'oggetto come primo parametro.


Questo in realtà è quello che stavo cercando!
Dejv,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.