Fungsi PHP dengan Parameter Opsional

107

Saya telah menulis fungsi PHP yang dapat menerima 10 parameter, tetapi hanya 2 yang diperlukan. Kadang-kadang, saya ingin menentukan parameter kedelapan, tetapi saya tidak ingin mengetikkan string kosong untuk setiap parameter sampai saya mencapai yang kedelapan.

Satu ide yang saya miliki adalah meneruskan fungsi yang diabstraksi dengan berbagai parameter yang meneruskannya ke fungsi sebenarnya.

Apakah ada cara yang lebih baik untuk mengatur fungsi sehingga saya hanya dapat mengirimkan parameter yang saya inginkan?

pengguna481826
sumber
Itu aneh. Fungsi built-in di php mungkin memiliki parameter opsional. Jadi mengapa kita tidak bisa membangun fungsi seperti itu?
Rodrigo
2
Perhatikan bahwa banyak dari jawaban ini sudah KELUAR ... PHP sekarang mendukung fungsi dengan daftar argumen panjang variabel .
ashleedawg

Jawaban:

62

Buat fungsi tersebut mengambil satu parameter: sebuah array. Meneruskan parameter aktual sebagai nilai dalam larik.


Sunting: tautan di komentar Pekka hampir merangkumnya.

Matt Ball
sumber
1
Itu aneh. Fungsi built-in di php mungkin memiliki parameter opsional. Jadi mengapa kita tidak bisa membangun fungsi seperti itu?
Rodrigo
1
@Rodrigo benar-benar bisa dilakukan untuk mendefinisikan fungsi seperti itu. Mereka adalah opsional posisi, yang cukup buruk untuk apa pun di luar parameter opsional tunggal.
Matt Ball
1
Oke, saya mencoba dengan [], sekarang saya melihat cara melakukannya di sini: stackoverflow.com/a/34869/1086511
Rodrigo
Masih ada lagi yang bisa dilakukan selain saran "gunakan larik" - lihat jawaban Walf untuk pertanyaan serupa dan contoh yang lebih mendalam di utas yang sama
DJDave
63

Apa yang telah saya lakukan dalam hal ini adalah melewatkan array, di mana kuncinya adalah nama parameter, dan nilainya adalah nilainya.

$optional = array(
  "param" => $param1,
  "param2" => $param2
);

function func($required, $requiredTwo, $optional) {
  if(isset($optional["param2"])) {
    doWork();
  }
}
Rabbott
sumber
Sebagai contoh, bukankah $ opsional perlu disetel global di dalam fungsi?
pengguna481826
1
global? tidak..? Anda membuat larik itu sebelum memanggil fungsi tersebut, dan Anda meneruskannya. Kode saya adalah contoh deskripsi Matt Balls tentang apa yang harus dilakukan.
Rabbott
Masih ada lagi yang bisa dilakukan selain saran "gunakan larik" - lihat jawaban Walf untuk pertanyaan serupa dan contoh yang lebih mendalam di utas yang sama
DJDave
45

Untuk mencapai apa yang Anda inginkan, gunakan larik Seperti yang dikatakan Rabbot (meskipun ini bisa menyusahkan untuk didokumentasikan / dipelihara jika digunakan secara berlebihan). Atau gunakan saja argumen opsional tradisional.

//My function with tons of optional params
function my_func($req_a, $req_b, $opt_a = NULL, $opt_b = NULL, $opt_c = NULL)
{
  //Do stuff
}
my_func('Hi', 'World', null, null, 'Red');

Namun, saya biasanya menemukan bahwa ketika saya mulai menulis fungsi / metode dengan banyak argumen - lebih sering daripada tidak itu adalah bau kode, dan dapat difaktorkan ulang / disarikan menjadi sesuatu yang jauh lebih bersih.

//Specialization of my_func - assuming my_func itself cannot be refactored
function my_color_func($reg_a, $reg_b, $opt = 'Red')
{
  return my_func($reg_a, $reg_b, null, null, $opt);
}
my_color_func('Hi', 'World');
my_color_func('Hello', 'Universe', 'Green');
Kayla Rose
sumber
Pada tahun 2010, gagasan seperti 'bau kode', 'pemfaktoran ulang' atau 'pemeliharaan kode' tidak populer di komunitas kami. Anda memiliki langkah sebelum kebanyakan dari kita :)
Billal Begueradj
15

Di PHP 5.6 dan yang lebih baru, daftar argumen mungkin menyertakan ... token untuk menunjukkan bahwa fungsi tersebut menerima sejumlah variabel argumen. Argumen akan diteruskan ke variabel yang diberikan sebagai array; sebagai contoh:

Contoh Menggunakan ... untuk mengakses argumen variabel

<?php
function sum(...$numbers) {
    $acc = 0;
    foreach ($numbers as $n) {
        $acc += $n;
    }
    return $acc;
}

echo sum(1, 2, 3, 4);
?>

Contoh di atas akan menampilkan:

10

Argumen panjang variabel mencantumkan Dokumentasi PHP

Mentos1386
sumber
Tanggapan ini membutuhkan lebih banyak poin. Tidak cocok untuk skenario kasus khusus saya tetapi informasi yang baik dan mudah dipahami. PHP 7.3 akan segera hadir! 5.6 dan 7 adalah EOL.
AdheneManx
12

Anda bisa menyetel nilai default ke null.

<?php
function functionName($value, $value2 = null) {
// do stuff
}
Blake Stevenson
sumber
2
Jawaban terbaik, tapi tolong ganti nulldengan non-bit pada tipe tanggal. misalnya array()untuk array
Mohamed hesham
Terima kasih ... Ini yang saya cari
Davide De Maestri
12

CATATAN: Ini adalah jawaban lama, untuk PHP 5.5 dan di bawahnya. PHP 5.6+ mendukung argumen default

Di PHP 5.5 dan yang lebih lama, Anda dapat mencapai ini dengan menggunakan salah satu dari 2 metode berikut:

  • menggunakan fungsi func_num_args () dan func_get_arg () ;
  • menggunakan argumen NULL;

Cara Penggunaan

function method_1()
{
  $arg1 = (func_num_args() >= 1)? func_get_arg(0): "default_value_for_arg1";
  $arg2 = (func_num_args() >= 2)? func_get_arg(1): "default_value_for_arg2";
}

function method_2($arg1 = null, $arg2 = null)
{
  $arg1 = $arg1? $arg1: "default_value_for_arg1";
  $arg2 = $arg2? $arg2: "default_value_for_arg2";
}

Saya lebih suka metode kedua karena bersih dan mudah dimengerti, tetapi terkadang Anda mungkin memerlukan metode pertama.

Daniel Loureiro
sumber
1
Anda membutuhkan double "=" di sini atau semua ekspresi akan mengembalikan nilai true. Juga, ekspresi dalam contoh ke-2 akan selalu mengembalikan nilai true karena variabel selalu sama dengan dirinya sendiri.
chuckieDub
poin bagus, tapi ini benar-benar berhasil. Dalam PHP kode ini $x = null; if ($x) echo "true"; else echo "false";akan mencetak "false", meskipun $ x var memiliki nilai ("null" dalam kode ini). Juga, di kedua metode kami menggunakan operator terner, jadi gunakanlah satu "=" yang benar. Jika Anda menguji dengan method(); method(1); method(1, 2);, maka panggilan pertama akan mengaitkan arg1 dan arg2 dengan nilai default, panggilan kedua akan mengaitkan argumen kedua dengan nilai default dan "1" untuk argumen pertama. Panggilan terakhir tidak akan mengasosiasikan nilai default.
Daniel Loureiro
1
function method_2 ($ arg1 = "default_value_fot_arg1", $ arg2 = "default_value_fot_arg2") {jadi php menangani hal-hal parameter dan Anda juga dapat memberikan null sebagai parameter (mengapa orang menggunakan null Saya tidak tahu)
nerkn
1
@nerkn, Anda benar, PHP saat ini mendukung argumen default. Lol, saya ingat ketika kami harus membuat banyak solusi untuk mencapai hal-hal sederhana. Waktu yang baik: P Anda masih dapat melihat pendekatan tersebut dalam kode lama (sebelum 5.5), meskipun.
Daniel Loureiro
4

Saya rasa, Anda juga bisa menggunakan objek sebagai params-transportes.

$myParam = new stdClass();
$myParam->optParam2 = 'something';
$myParam->optParam8 = 3;
theFunction($myParam);

function theFunction($fparam){      
  return "I got ".$fparam->optParam8." of ".$fparam->optParam2." received!";
}

Tentu saja, Anda harus menetapkan nilai default untuk "optParam8" dan "optParam2" dalam fungsi ini, dalam kasus lain Anda akan mendapatkan "Pemberitahuan: Properti yang tidak ditentukan: stdClass :: $ optParam2"

Jika menggunakan array sebagai parameter fungsi, saya suka cara ini untuk mengatur nilai default:

function theFunction($fparam){
   $default = array(
      'opt1' => 'nothing',
      'opt2' => 1
   );
   if(is_array($fparam)){
      $fparam = array_merge($default, $fparam);
   }else{
      $fparam = $default;
   }
   //now, the default values are overwritten by these passed by $fparam
   return "I received ".$fparam['opt1']." and ".$fparam['opt2']."!";
}
psad
sumber
2

Jika hanya dua nilai yang diperlukan untuk membuat objek dengan status yang valid, Anda dapat dengan mudah menghapus semua argumen opsional lainnya dan menyediakan setter untuk mereka (kecuali Anda tidak ingin mereka berubah saat runtime). Kemudian buat instance objek dengan dua argumen yang diperlukan dan setel yang lain sesuai kebutuhan melalui penyetel.

Bacaan lebih lanjut

Gordon
sumber
2

Saya tahu ini adalah posting lama, tetapi saya mengalami masalah seperti OP dan inilah yang saya temukan.

Contoh larik yang bisa Anda lewati. Anda dapat memesan ulang ini jika pesanan tertentu diperlukan, tetapi untuk pertanyaan ini ini akan melakukan apa yang diminta.

$argument_set = array (8 => 'lots', 5 => 'of', 1 => 'data', 2 => 'here');

Ini dapat dikelola, mudah dibaca dan titik ekstraksi data dapat ditambahkan dan dihapus pada saat-saat tertentu di mana saja dalam pengkodean dan masih menghindari penulisan ulang besar-besaran. Saya menggunakan kunci integer untuk menghitung dengan pertanyaan asli OP tetapi kunci string dapat digunakan dengan mudah. Bahkan untuk keterbacaan saya akan menyarankannya.

Tempelkan ini di file eksternal untuk kemudahan

function unknown_number_arguments($argument_set) {

    foreach ($argument_set as $key => $value) {

        # create a switch with all the cases you need. as you loop the array 
        # keys only your submitted $keys values will be found with the switch. 
        switch ($key) {
            case 1:
                # do stuff with $value
                break;
            case 2:
                # do stuff with $value;
                break;
            case 3:
                # key 3 omitted, this wont execute 
                break;
            case 5:
                # do stuff with $value;
                break;
            case 8:
                # do stuff with $value;
                break;
            default:
                # no match from the array, do error logging?
                break;
        }
    }
return;
}

letakkan ini di awal jika file tersebut.

$argument_set = array(); 

Cukup gunakan ini untuk menetapkan bagian data berikutnya menggunakan penomoran / penamaan sesuai dengan dari mana data itu berasal.

$argument_set[1][] = $some_variable; 

Dan akhirnya lewati array

unknown_number_arguments($argument_set);
Chris
sumber
1
function yourFunction($var1, $var2, $optional = Null){
   ... code
}

Anda dapat membuat fungsi biasa dan kemudian menambahkan variabel opsional Anda dengan memberinya nilai Null default.

Null tetap sebuah nilai, jika Anda tidak memanggil fungsi dengan nilai untuk variabel itu, tidak akan kosong jadi tidak ada kesalahan.

antoine serry
sumber
2
Bisakah Anda menjelaskan semua itu lebih jauh? Kode yang diberikan tidak valid secara sintaksis, karena nama variabel tidak boleh dimulai dengan angka
Nico Haase
0

Jika Anda biasanya hanya meneruskan nilai ke-8, Anda dapat menyusun ulang parameter Anda menjadi yang pertama. Anda hanya perlu menentukan parameter sampai yang terakhir ingin Anda setel.

Jika Anda menggunakan nilai yang berbeda, Anda memiliki 2 opsi.

Salah satunya adalah membuat satu set fungsi pembungkus yang mengambil parameter berbeda dan menetapkan default pada yang lain. Ini berguna jika Anda hanya menggunakan sedikit kombinasi, tetapi dapat menjadi sangat berantakan dengan cepat.

Opsi lainnya adalah melewatkan array di mana kuncinya adalah nama parameter. Anda kemudian dapat memeriksa apakah ada nilai dalam array dengan kunci, dan jika tidak menggunakan default. Tetapi sekali lagi, ini bisa menjadi berantakan dan menambahkan banyak kode tambahan jika Anda memiliki banyak parameter.

Alan Geleynse
sumber
0

PHP memungkinkan argumen default ( tautan ). Dalam kasus Anda, Anda dapat mendefinisikan semua parameter dari 3 sampai 8 sebagai NULL atau sebagai string kosong "" tergantung pada kode fungsi Anda. Dengan cara ini, Anda dapat memanggil fungsi hanya menggunakan dua parameter pertama.

Sebagai contoh:

<?php
  function yourFunction($arg1, $arg2, $arg3=NULL, $arg4=NULL, $arg5=NULL, $arg6=NULL, $arg7=NULL, $arg8=NULL){
echo $arg1;
echo $arg2;
if(isset($arg3)){echo $arg3;}
# other similar statements for $arg4, ...., $arg5
if(isset($arg8)){echo $arg8;}
}
Andrés Luna
sumber
Ide yang menarik ... namun proposal Anda tidak menyelesaikan masalah. Faktanya, jika Anda menambahkan informasi tentang argumen apa yang di-echo-kan (mis. Dengan menggunakan echo " this is arg3: " . $arg3;, dll., Anda akan melihat bahwa pemanggilan eg yourFunction(3, 2, $arg8=5);akan dicetak 32 this is arg3: 5. Masalahnya adalah bahwa posisi parameter masih penting ketika meneruskan parameter opsional dalam PHP ... nama parameter tidak cukup untuk memetakan nilai parameter ke nama parameter.
mastropi
0

Setel Null untuk mengabaikan parameter yang tidak ingin Anda gunakan, lalu setel parameter yang diperlukan sesuai posisinya.

 function myFunc($p1,$p2,$p3=Null,$p4=Null,$p5=Null,$p6=Null,$p7=Null,$p8=Null){
    for ($i=1; $i<9; $i++){
        $varName = "p$i";
        if (isset($$varName)){
            echo $varName." = ".$$varName."<br>\n";
        }
    }
}   

myFunc( "1", "2", Null, Null, Null, Null, Null, "eight" );
FERNANDO BARAZZETTI
sumber
-4
func( "1", "2", default, default, default, default, default, "eight" );
Flinsch
sumber
1
Ini bukan PHP yang valid. defaultadalah kata kunci dalam PHP .
Pang