Come passare un numero variabile di argomenti a una funzione PHP


115

Ho una funzione PHP che accetta un numero variabile di argomenti (usando func_num_args()e func_get_args()), ma il numero di argomenti che voglio passare alla funzione dipende dalla lunghezza di un array. C'è un modo per chiamare una funzione PHP con un numero variabile di argomenti?


1
Controllare la mia risposta per conoscere un operatore di splat in new php5.6: stackoverflow.com/a/23163963/1090562
Salvador Dali

Risposte:


132

Se hai i tuoi argomenti in un array, potresti essere interessato dal file call_user_func_array funzione.

Se il numero di argomenti che vuoi passare dipende dalla lunghezza di un array, probabilmente significa che puoi impacchettarli in un array e usarlo per il secondo parametro di call_user_func_array.

Gli elementi di quell'array passato verranno quindi ricevuti dalla funzione come parametri distinti.


Ad esempio, se hai questa funzione:

function test() {
  var_dump(func_num_args());
  var_dump(func_get_args());
}

Puoi impacchettare i tuoi parametri in un array, come questo:

$params = array(
  10,
  'glop',
  'test',
);

E, quindi, chiama la funzione:

call_user_func_array('test', $params);

Questo codice produrrà:

int 3

array
  0 => int 10
  1 => string 'glop' (length=4)
  2 => string 'test' (length=4)

cioè 3 parametri; esattamente come la funzione è stata chiamata in questo modo:

test(10, 'glop', 'test');

1
Si Grazie. call_user_func_array () è esattamente la funzione che stavo cercando.
nohat

È possibile utilizzare call_user_func_array () con una chiamata al metodo dell'oggetto?
nohat

6
@nohat: sei il benvenuto :-) ;; sull'uso di un metodo di un oggetto: sì, puoi, usando qualcosa come array ($ obj, 'methodName') come primo parametro ;; in realtà, puoi passare qualsiasi "callback" che desideri a quella funzione. Per ulteriori informazioni sui callback, vedere php.net/callback#language.types.callback
Pascal MARTIN

58

Questo è ora possibile con PHP 5.6.x , utilizzando l'operatore ... (noto anche come operatore splat in alcune lingue):

Esempio:

function addDateIntervalsToDateTime( DateTime $dt, DateInterval ...$intervals )
{
    foreach ( $intervals as $interval ) {
        $dt->add( $interval );
    }
    return $dt;
}

addDateIntervaslToDateTime( new DateTime, new DateInterval( 'P1D' ), 
        new DateInterval( 'P4D' ), new DateInterval( 'P10D' ) );

1
L' elenco degli argomenti delle variabili digitate è una funzionalità introdotta in PHP 7 .
Daniele Orlando

46

In un nuovo Php 5.6 , puoi usare ... operatorinvece di usare func_get_args().

Quindi, usando questo, puoi ottenere tutti i parametri che passi:

function manyVars(...$params) {
   var_dump($params);
}

3
Maggiori informazioni qui: php.net/manual/en/...
fracz

Dal collegamento @fracz, OP sta cercando di creare una "funzione variadica".
Nathan Arthur

40

A partire da PHP 5.6 , è possibile specificare un elenco di argomenti variabili con l' ...operatore.

function do_something($first, ...$all_the_others)
{
    var_dump($first);
    var_dump($all_the_others);
}

do_something('this goes in first', 2, 3, 4, 5);

#> string(18) "this goes in first"
#>
#> array(4) {
#>   [0]=>
#>   int(2)
#>   [1]=>
#>   int(3)
#>   [2]=>
#>   int(4)
#>   [3]=>
#>   int(5)
#> }

Come puoi vedere, l' ...operatore raccoglie l'elenco delle variabili di argomenti in un array.

Se hai bisogno di passare gli argomenti della variabile a un'altra funzione, ...può comunque aiutarti.

function do_something($first, ...$all_the_others)
{
    do_something_else($first, ...$all_the_others);
    // Which is translated to:
    // do_something_else('this goes in first', 2, 3, 4, 5);
}

Poiché PHP 7 , l'elenco di argomenti variabile può essere forzato ad essere tutti dello stesso tipo anche.

function do_something($first, int ...$all_the_others) { /**/ }

11

Per chi cerca un modo per farlo con $object->method:

call_user_func_array(array($object, 'method_name'), $array);

Ho avuto successo con questo in una funzione di costruzione che chiama una variabile nome_metodo con parametri variabili.


2
Puoi anche usare$object->method_name(...$array);
Yoann Kergall

Andando oltre, se vuoi passare per riferimento, usa$object->method_name(&...$args);
Fabien Haddadi

4

Puoi semplicemente chiamarlo.

function test(){        
     print_r(func_get_args());
}

test("blah");
test("blah","blah");

Produzione:

Array ([0] => blah) Array ([0] => blah [1] => blah)


Se capisco correttamente l'OP, il problema non è ricevere i parametri, ma chiamare la funzione con un numero variabile di parametri.
Pascal MARTIN,

1
Allora non ho capito correttamente l'OP. Un array sarebbe sicuramente la strada da percorrere, quindi. Poi di nuovo, potrebbe semplicemente passare l'array direttamente a test (), no?
Donnie C,

1
Anche passare un array potrebbe essere una soluzione, anzi - Se ho capito bene ^^
Pascal MARTIN

1
Vecchia domanda ma a proposito, un array funziona bene ma il passaggio di argomenti effettivi ti consente di utilizzare i valori predefiniti di PHP per argomenti nulli, il che consente di risparmiare un sacco di brutti controlli per vedere se l'array contiene valori particolari.
Endophage


1

Una vecchia domanda, lo so, tuttavia, nessuna delle risposte qui fa davvero un buon lavoro nel rispondere semplicemente alla domanda.

Ho appena giocato con php e la soluzione è simile a questa:

function myFunction($requiredArgument, $optionalArgument = "default"){
   echo $requiredArgument . $optionalArgument;
}

Questa funzione può fare due cose:

Se viene chiamato solo con il parametro richiesto: myFunction("Hi") Stamperà "Hi default"

Ma se viene chiamato con il parametro opzionale: myFunction("Hi","me") Stamperà "Ciao me";

Spero che questo aiuti chiunque stia cercando questo lungo la strada.


2
Non sei riuscito a capire la domanda. OP stava chiedendo argomenti che non doveva definire esplicitamente nella firma della funzione , ma può ancora passare valori come argomenti alla funzione. Ad esempio, la firma della funzione non ha alcun argomento definito (opzionale o meno), ma quando lo richiede, OP può inviare 45 valori diversi come argomenti alla funzione.
a20

0

Ecco una soluzione che utilizza il metodo magico __invoke

(Disponibile da php 5.3)

class Foo {
    public function __invoke($method=null, $args=[]){
        if($method){
            return call_user_func_array([$this, $method], $args);
        }
        return false;
    }

    public function methodName($arg1, $arg2, $arg3){

    }
}

Dalla stessa classe:

$this('methodName', ['arg1', 'arg2', 'arg3']);

Da un'istanza di un oggetto:

$obj = new Foo;
$obj('methodName', ['arg1', 'arg2', 'arg3'])

Questo fondamentalmente sta usando call_user_func_arraycome dichiarato dalla risposta più votata nel 2009. Forse c'è un punto per avvolgere un extra __invokeattorno ad esso, ma non lo vedo.
a20
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.