Melewati Array sebagai Argumen, bukan Array, dalam PHP

148

Saya sepertinya ingat bahwa di PHP ada cara untuk melewatkan array sebagai daftar argumen untuk suatu fungsi, mendereferensi array ke dalam func($arg1, $arg2)cara standar . Tapi sekarang saya bingung bagaimana melakukannya. Saya ingat cara melintas dengan referensi, cara "glob" parameter yang masuk ... tetapi tidak bagaimana untuk membatalkan daftar array ke dalam daftar argumen.

Mungkin sesederhana itu func(&$myArgs), tapi aku cukup yakin bukan. Tapi, sayangnya, panduan php.net belum membocorkan apa pun sejauh ini. Bukan berarti saya harus menggunakan fitur khusus ini selama setahun terakhir.

Robert K.
sumber

Jawaban:

178

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

call_user_func_array('func',$myArgs);
vartec
sumber
1
Saya bisa bersumpah bahwa itu juga tidak berfungsi, seperti karakter awalan atau sesuatu. Terima kasih.
Robert K
8
Tapi saya tidak tahu Python! Saya harus secara tidak sengaja psikis ...: D
Robert K
45
Argumen unpacking, demikian sebutannya, akan ditambahkan dalam PHP 5.6 ( wiki.php.net/rfc/argument_unpacking ). Ini akan menggunakan 'operator percikan': '...'. Sintaksnya: $args = [1,2,3]; function(...$args){}
arothuis
4
tetapi bagaimana jika fungsi yang ingin Anda panggil adalah metode instance pada objek, bukan nama fungsi di ruang global?
ahnbizcad
6
@ ahnbizcad maka Anda harus menggunakan callable, yang menggunakan yang sama call_user_func_array, hanya dengan array di mana elemen pertama adalah objek, dan yang kedua adalah metode. Misalnyacall_user_func_array([$object, 'method'], $myArgs);
SteveB
149

Seperti yang telah disebutkan , pada PHP 5.6+ Anda dapat (harus!) Menggunakan ...token (alias "operator percikan", bagian dari fungsionalitas fungsi variadik ) untuk dengan mudah memanggil suatu fungsi dengan sejumlah argumen:

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

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

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

// 'Hello World'

Catatan: item array dipetakan ke argumen dengan posisi mereka di dalam array, bukan kunci mereka.

Sesuai komentar CarlosCarucce , bentuk argumen membongkar ini adalah metode tercepat sejauh ini dalam semua kasus. Dalam beberapa perbandingan, ini lebih cepat 5x daricall_user_func_array .

Ke samping

Karena saya pikir ini sangat berguna (meskipun tidak terkait langsung dengan pertanyaan): Anda dapat mengetikkan petunjuk parameter percikan operator dalam definisi fungsi Anda untuk memastikan semua nilai yang diteruskan cocok dengan jenis tertentu.

(Ingatlah bahwa melakukan ini HARUS menjadi yang terakhir parameter Anda tetapkan dan bahwa ia menggabungkan semua parameter yang dilewatkan ke fungsi ke dalam array.)

Ini bagus untuk memastikan array berisi item dari tipe tertentu:

<?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
sumber
7
Ini memiliki peningkatan kinerja yang luar biasa call_user_func_array. Jadi jika Anda menggunakan php 5.6+ saya akan merekomendasikan yang ini. Berikut ini adalah tes , yang dikutip dalam wiki php resmi
CarlosCarucce
2
Sangat disayangkan ini bukan jawaban yang ditandai. Pasti jauh lebih baik
unforgiven1987
81

Perhatikan juga bahwa jika Anda ingin menerapkan metode instance ke array, Anda harus meneruskan fungsi sebagai:

call_user_func_array(array($instance, "MethodName"), $myArgs);
Jeff Ober
sumber
4
@understack $foo->bar()Contoh pada halaman tertaut menyarankan bahwa seharusnya array($instance, "MethodName").
Paul Calcraft
11
Luar biasa, saya menggunakan ini untuk menghindari duplikasi argumen konstruktor di kelas anak :)call_user_func_array(array(parent, "__construct"), func_get_args());
Jason
10

Demi kelengkapan, pada PHP 5.1 ini juga berfungsi:

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

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

Untuk metode yang Anda gunakan ReflectionMethod :: invokeArgs sebagai gantinya dan meneruskan objek sebagai parameter pertama.

DanMan
sumber
Ini sebenarnya yang saya cari!
Dejv