Cara melewatkan sejumlah variabel argumen ke fungsi PHP

115

Saya memiliki fungsi PHP yang mengambil sejumlah variabel argumen (menggunakan func_num_args()dan func_get_args()), tetapi jumlah argumen yang ingin saya sampaikan fungsi tersebut tergantung pada panjang array. Apakah ada cara untuk memanggil fungsi PHP dengan sejumlah variabel argumen?

nohat
sumber
1
Periksa jawaban saya untuk mempelajari tentang operator percikan di php5.6 baru: stackoverflow.com/a/23163963/1090562
Salvador Dali

Jawaban:

132

Jika Anda memiliki argumen dalam array, Anda mungkin tertarik dengan call_user_func_arrayfungsinya.

Jika jumlah argumen yang ingin Anda sampaikan bergantung pada panjang array, itu mungkin berarti Anda dapat mengemasnya ke dalam array sendiri - dan menggunakannya untuk parameter kedua call_user_func_array.

Elemen dari larik yang Anda lewati kemudian akan diterima oleh fungsi Anda sebagai parameter yang berbeda.


Misalnya, jika Anda memiliki fungsi ini:

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

Anda dapat mengemas parameter Anda ke dalam array, seperti ini:

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

Dan, kemudian, panggil fungsinya:

call_user_func_array('test', $params);

Kode ini akan menghasilkan:

int 3

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

yaitu, 3 parameter; persis seperti iof fungsinya disebut seperti ini:

test(10, 'glop', 'test');
Pascal MARTIN
sumber
1
Ya terima kasih. call_user_func_array () persis dengan fungsi yang saya cari.
nohat
Apakah mungkin untuk menggunakan call_user_func_array () dengan pemanggilan metode objek?
nohat
6
@nohat: sama-sama :-) ;; tentang menggunakan metode objek: ya, Anda bisa, menggunakan sesuatu seperti array ($ obj, 'methodName') sebagai parameter pertama ;; sebenarnya, Anda dapat meneruskan "callback" apa pun yang Anda inginkan ke fungsi itu. Untuk informasi lebih lanjut tentang panggilan balik, lihat php.net/callback#language.types.callback
Pascal MARTIN
58

Ini sekarang dimungkinkan dengan PHP 5.6.x , menggunakan operator ... (juga dikenal sebagai operator percikan dalam beberapa bahasa):

Contoh:

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' ) );
JCM
sumber
1
Daftar argumen variabel yang diketik adalah fitur yang diperkenalkan di PHP 7 .
Daniele Orlando
46

Di Php 5.6 baru , Anda dapat menggunakan ... operatordaripada menggunakan func_get_args().

Jadi, dengan menggunakan ini, Anda bisa mendapatkan semua parameter yang Anda berikan:

function manyVars(...$params) {
   var_dump($params);
}
Salvador Dali
sumber
3
Info lebih lanjut di sini: php.net/manual/en/…
fracz
Dari tautan @fracz, OP mencoba membuat "fungsi variadic".
Nathan Arthur
40

Sejak PHP 5.6 , daftar argumen variabel dapat ditentukan dengan ...operator.

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)
#> }

Seperti yang Anda lihat, ...operator mengumpulkan daftar variabel argumen dalam sebuah array.

Jika Anda perlu meneruskan argumen variabel ke fungsi lain, itu ...masih bisa membantu Anda.

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

Sejak PHP 7 , daftar variabel argumen dapat dipaksa menjadi semua tipe yang sama juga.

function do_something($first, int ...$all_the_others) { /**/ }
Daniele Orlando
sumber
11

Bagi mereka yang mencari cara untuk melakukan ini dengan $object->method:

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

Saya berhasil dengan ini dalam fungsi konstruksi yang memanggil nama_metode variabel dengan parameter variabel.

danilo
sumber
2
Anda juga dapat menggunakan$object->method_name(...$array);
Yoann Kergall
Lebih jauh, jika Anda ingin melewati referensi, gunakan$object->method_name(&...$args);
Fabien Haddadi
4

Anda bisa menyebutnya begitu saja.

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

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

Keluaran:

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

Donnie C.
sumber
Jika saya memahami OP dengan benar, masalahnya bukan menerima parameter, tetapi memanggil fungsi dengan sejumlah parameter variabel.
Pascal MARTIN
1
Saya tidak memahami OP dengan benar, lalu. Sebuah array pasti akan menjadi cara untuk pergi, kalau begitu. Kemudian lagi, dia bisa meneruskan array langsung ke test (), bukan?
Donnie C
1
Meneruskan sebuah array mungkin bisa menjadi solusi juga, memang - Jika saya mengerti dengan benar ^^
Pascal MARTIN
1
Pertanyaan lama tetapi fyi, sebuah array berfungsi dengan baik tetapi meneruskan argumen aktual memungkinkan Anda untuk menggunakan nilai default PHP untuk argumen null yang menghemat banyak pemeriksaan yang buruk untuk melihat apakah array tersebut berisi nilai tertentu.
Endophage
1

Sebuah pertanyaan lama, saya tahu, bagaimanapun, tidak ada jawaban di sini yang benar-benar berfungsi dengan baik hanya dengan menjawab pertanyaan itu.

Saya baru saja bermain-main dengan php dan solusinya terlihat seperti ini:

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

Fungsi ini dapat melakukan dua hal:

Jika dipanggil dengan hanya parameter yang diperlukan: myFunction("Hi") Ini akan mencetak "Hi default"

Tetapi jika dipanggil dengan parameter opsional: myFunction("Hi","me") Ini akan mencetak "Hai saya";

Saya harap ini membantu siapa saja yang mencari ini di masa mendatang.

Alex
sumber
2
Anda gagal memahami pertanyaannya. OP bertanya tentang argumen yang tidak harus dia definisikan secara eksplisit dalam tanda tangan fungsi - namun dia masih bisa meneruskan nilai sebagai argumen ke fungsi. Misalnya, tanda tangan fungsi tidak memiliki apapun argumen didefinisikan (opsional atau tidak), tetapi ketika ia membutuhkan itu, OP dapat mengirim 45 nilai yang berbeda sebagai argumen untuk fungsi.
a20
0

Berikut adalah solusi menggunakan metode ajaib __invoke

(Tersedia sejak 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){

    }
}

Dari dalam kelas yang sama:

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

Dari sebuah contoh objek:

$obj = new Foo;
$obj('methodName', ['arg1', 'arg2', 'arg3'])
Dieter Gribnitz
sumber
Ini pada dasarnya menggunakan call_user_func_arrayseperti yang dinyatakan oleh jawaban pilihan teratas pada tahun 2009. Mungkin ada gunanya membungkus tambahan __invokedi sekitarnya - tapi saya tidak melihatnya.
a20