ฟังก์ชัน PHP พร้อมพารามิเตอร์เสริม


107

ฉันได้เขียนฟังก์ชัน PHP ที่สามารถรับพารามิเตอร์ได้ 10 พารามิเตอร์ แต่จำเป็นต้องใช้เพียง 2 ตัวเท่านั้น บางครั้งฉันต้องการกำหนดพารามิเตอร์ที่แปด แต่ฉันไม่ต้องการพิมพ์สตริงว่างสำหรับแต่ละพารามิเตอร์จนกว่าฉันจะไปถึงพารามิเตอร์ที่แปด

ความคิดหนึ่งที่ฉันมีคือการส่งผ่านฟังก์ชันนามธรรมที่มีอาร์เรย์ของพารามิเตอร์ซึ่งส่งผ่านไปยังฟังก์ชันจริง

มีวิธีที่ดีกว่าในการตั้งค่าฟังก์ชันเพื่อให้สามารถส่งผ่านเฉพาะพารามิเตอร์ที่ต้องการได้หรือไม่


4
ที่เกี่ยวข้อง: stackoverflow.com/questions/2112913
Pekka

นั่นเป็นเรื่องแปลก ฟังก์ชันในตัวใน php อาจมีพารามิเตอร์เสริม แล้วทำไมเราถึงสร้างฟังก์ชันแบบนั้นไม่ได้?
Rodrigo

2
ทราบว่าหลายคำตอบเหล่านี้จะล้าสมัย ... PHP ในขณะนี้สนับสนุนฟังก์ชั่นที่มีรายการอาร์กิวเมนต์ตัวแปรที่มีความยาว
ashleedawg

คำตอบ:


62

ทำให้ฟังก์ชันใช้พารามิเตอร์หนึ่งตัว: อาร์เรย์ ส่งผ่านพารามิเตอร์จริงเป็นค่าในอาร์เรย์


แก้ไข: ลิงก์ในความคิดเห็นของ Pekkaเกี่ยวกับผลรวม


1
นั่นเป็นเรื่องแปลก ฟังก์ชันในตัวใน php อาจมีพารามิเตอร์เสริม แล้วทำไมเราถึงสร้างฟังก์ชันแบบนั้นไม่ได้?
Rodrigo

1
@Rodrigo สามารถกำหนดฟังก์ชันเช่นนี้ได้อย่างแน่นอน แม้ว่าจะเป็นตัวเลือกตำแหน่งซึ่งค่อนข้างน่ากลัวสำหรับสิ่งที่อยู่นอกเหนือพารามิเตอร์ทางเลือกเดียว
Matt Ball

1
โอเคฉันพยายามกับ [] ตอนนี้ฉันดูวิธีการที่นี่: stackoverflow.com/a/34869/1086511
Rodrigo

ยังมีอีกมากที่สามารถทำได้เพียงแค่คำแนะนำ "ใช้อาร์เรย์" - ดูคำตอบของ Walf สำหรับคำถามที่คล้ายกันและตัวอย่างเชิงลึกในหัวข้อเดียวกัน
DJDave

63

สิ่งที่ฉันได้ทำในกรณีนี้คือส่งอาร์เรย์โดยที่คีย์คือชื่อพารามิเตอร์และค่าคือค่า

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

function func($required, $requiredTwo, $optional) {
  if(isset($optional["param2"])) {
    doWork();
  }
}

สำหรับตัวอย่างของคุณไม่จำเป็นต้องตั้งค่า $ optional global ภายในฟังก์ชันหรือไม่?
user481826

1
โกลบอล? ไม่ .. ? คุณสร้างอาร์เรย์นั้นก่อนที่จะเรียกใช้ฟังก์ชันและส่งผ่านไป โค้ดของฉันคือตัวอย่างคำอธิบายของ Matt Balls เกี่ยวกับสิ่งที่ควรทำ
Rabbott

ยังมีอีกมากที่สามารถทำได้เพียงแค่คำแนะนำ "ใช้อาร์เรย์" - ดูคำตอบของ Walf สำหรับคำถามที่คล้ายกันและตัวอย่างเชิงลึกในหัวข้อเดียวกัน
DJDave

45

เพื่อให้บรรลุสิ่งที่คุณต้องการให้ใช้อาร์เรย์เหมือนที่ Rabbot กล่าวไว้ (แม้ว่าสิ่งนี้จะกลายเป็นความเจ็บปวดในการจัดทำเอกสาร / บำรุงรักษาหากใช้มากเกินไป) หรือเพียงแค่ใช้ args ทางเลือกแบบดั้งเดิม

//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');

อย่างไรก็ตามฉันมักจะพบว่าเมื่อฉันเริ่มเขียนฟังก์ชัน / วิธีการที่มีข้อโต้แย้งมากมาย - บ่อยกว่านั้นไม่ใช่กลิ่นรหัสและสามารถนำมาสรุปใหม่ / แยกส่วนเป็นสิ่งที่สะอาดกว่าได้มาก

//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');

ในปี 2010 แนวคิดเช่น 'code smell', 'refactoring' หรือ 'code maintenance' ไม่เป็นที่นิยมในชุมชนของเรา คุณมีก้าวก่อนพวกเราส่วนใหญ่ :)
Billal Begueradj

15

ใน PHP 5.6 ขึ้นไปรายการอาร์กิวเมนต์อาจรวมถึง ... โทเค็นเพื่อแสดงว่าฟังก์ชันยอมรับอาร์กิวเมนต์ที่เป็นตัวแปร อาร์กิวเมนต์จะถูกส่งผ่านไปยังตัวแปรที่กำหนดเป็นอาร์เรย์ ตัวอย่างเช่น:

ตัวอย่างการใช้ ... เพื่อเข้าถึงอาร์กิวเมนต์ตัวแปร

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

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

ตัวอย่างข้างต้นจะแสดงผลลัพธ์:

10

อาร์กิวเมนต์ความยาวตัวแปรแสดงรายการเอกสาร PHP


คำตอบนี้สมควรได้รับคะแนนมากขึ้น ไม่เหมาะสำหรับสถานการณ์เฉพาะของฉัน แต่ข้อมูลที่ดีและเข้าใจง่าย PHP 7.3 กำลังจะมาในไม่ช้า! 5.6 และ 7 คือ EOL
AdheneManx

12

คุณสามารถตั้งค่าเริ่มต้นเป็นค่าว่างได้

<?php
function functionName($value, $value2 = null) {
// do stuff
}

2
คำตอบที่ดีที่สุด แต่โปรดแทนที่nullด้วยประเภทวันที่ที่ไม่ใช่บิต ตัวอย่างเช่นarray()อาร์เรย์
Mohamed Hesham

ขอบคุณ ... นี่คือสิ่งที่ฉันกำลังมองหา
Davide De Maestri

12

หมายเหตุ: นี่เป็นคำตอบเก่าสำหรับPHP 5.5และต่ำกว่า PHP 5.6+ รองรับอาร์กิวเมนต์เริ่มต้น

ใน PHP 5.5 และต่ำกว่าคุณสามารถทำได้โดยใช้หนึ่งใน 2 วิธีต่อไปนี้:

  • ใช้func_num_args ()และfunc_get_arg ()ฟังก์ชั่น;
  • ใช้อาร์กิวเมนต์ NULL

วิธีใช้

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

ฉันชอบวิธีที่สองมากกว่าเพราะมันสะอาดและเข้าใจง่าย แต่บางครั้งคุณอาจต้องใช้วิธีแรก


1
คุณต้องมี "=" สองเท่าที่นี่มิฉะนั้นนิพจน์ทั้งหมดจะคืนค่าจริง นอกจากนี้นิพจน์ในตัวอย่างที่ 2 จะคืนค่าจริงเนื่องจากตัวแปรจะเท่ากับตัวมันเองเสมอ
chuckieDub

จุดดี แต่ใช้งานได้จริง ใน PHP โค้ดนี้$x = null; if ($x) echo "true"; else echo "false";จะพิมพ์ "false" แม้ว่า $ x var จะมีค่า ("null" ในโค้ดนี้ก็ตาม) นอกจากนี้ในทั้งสองวิธีเรากำลังใช้ตัวดำเนินการ ternary ดังนั้นจึงถูกต้องให้ใช้ "=" เพียงตัวเดียว หากคุณทดสอบด้วยmethod(); method(1); method(1, 2);การเรียกครั้งแรกจะเชื่อมโยง arg1 และ arg2 กับค่าดีฟอลต์การเรียกที่สองจะเชื่อมโยงอาร์กิวเมนต์ที่สองกับค่าดีฟอลต์และ "1" สำหรับอาร์กิวเมนต์แรก การโทรครั้งสุดท้ายจะไม่เชื่อมโยงค่าเริ่มต้น
Daniel Loureiro

1
function method_2 ($ arg1 = "default_value_fot_arg1", $ arg2 = "default_value_fot_arg2") {ดังนั้น php จัดการกับพารามิเตอร์ต่างๆและคุณอาจส่งค่า null เป็นพารามิเตอร์ (ทำไมคนใช้ null ฉันไม่รู้)
nerkn

1
@nerkn คุณพูดถูกปัจจุบัน PHP รองรับอาร์กิวเมนต์เริ่มต้น ฮ่า ๆ ฉันจำได้ว่าเมื่อเราต้องการวิธีแก้ปัญหามากมายเพื่อให้บรรลุสิ่งง่ายๆ ช่วงเวลาที่ดี: P คุณยังสามารถดูแนวทางเหล่านี้ได้ในรหัสเก่า (ก่อนหน้า 5.5) แม้ว่า
Daniel Loureiro

4

ฉันคิดว่าคุณสามารถใช้วัตถุเป็นพารัมขนส่งได้เช่นกัน

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

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

แน่นอนคุณต้องตั้งค่าเริ่มต้นสำหรับ "optParam8" และ "optParam2" ในฟังก์ชันนี้ในกรณีอื่น ๆ คุณจะได้รับ "Notice: Undefined property: stdClass :: $ optParam2"

หากใช้อาร์เรย์เป็นพารามิเตอร์ฟังก์ชันฉันชอบวิธีนี้ในการตั้งค่าเริ่มต้น:

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']."!";
}

2

หากต้องการเพียงสองค่าในการสร้างอ็อบเจ็กต์ที่มีสถานะที่ถูกต้องคุณสามารถลบอาร์กิวเมนต์ที่เป็นทางเลือกอื่น ๆ ทั้งหมดและระบุตัวตั้งค่าสำหรับค่าเหล่านี้ (เว้นแต่คุณไม่ต้องการให้เปลี่ยนแปลงในขณะรันไทม์) จากนั้นเพียงสร้างอินสแตนซ์วัตถุด้วยอาร์กิวเมนต์ที่จำเป็นทั้งสองและตั้งค่าอื่น ๆ ตามต้องการผ่านตัวตั้ง

อ่านเพิ่มเติม


2

ฉันรู้ว่านี่เป็นโพสต์เก่า แต่ฉันมีปัญหาเช่น OP และนี่คือสิ่งที่ฉันคิดขึ้นมา

ตัวอย่างอาร์เรย์ที่คุณส่งผ่านได้ คุณสามารถสั่งซื้อใหม่ได้หากต้องการคำสั่งซื้อใดคำสั่งหนึ่ง แต่สำหรับคำถามนี้สิ่งนี้จะทำตามที่ถาม

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

สิ่งนี้สามารถจัดการได้อ่านง่ายและสามารถเพิ่มและลบจุดสกัดข้อมูลได้ในเวลาที่สังเกตเห็นได้ทุกที่ในการเข้ารหัสและยังหลีกเลี่ยงการเขียนซ้ำจำนวนมาก ฉันใช้คีย์จำนวนเต็มเพื่อนับรวมกับคำถามดั้งเดิมของ OP แต่สามารถใช้คีย์สตริงได้อย่างง่ายดาย ในความเป็นจริงเพื่อการอ่านฉันจะแนะนำ

ติดสิ่งนี้ในไฟล์ภายนอกเพื่อความสะดวก

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

วางไว้ที่จุดเริ่มต้นหากไฟล์.

$argument_set = array(); 

เพียงใช้สิ่งเหล่านี้เพื่อกำหนดส่วนต่อไปของข้อมูลให้ใช้การกำหนดหมายเลข / การตั้งชื่อตามที่มาของข้อมูล

$argument_set[1][] = $some_variable; 

และส่งอาร์เรย์ในที่สุด

unknown_number_arguments($argument_set);

1
function yourFunction($var1, $var2, $optional = Null){
   ... code
}

คุณสามารถสร้างฟังก์ชันปกติจากนั้นเพิ่มตัวแปรที่เป็นทางเลือกของคุณโดยให้ค่า Null เริ่มต้น

ค่า Null ยังคงเป็นค่าหากคุณไม่เรียกใช้ฟังก์ชันด้วยค่าสำหรับตัวแปรนั้นจะไม่ว่างเปล่าจึงไม่มีข้อผิดพลาด


2
คุณช่วยอธิบายเพิ่มเติมได้ไหม รหัสที่ระบุไม่ถูกต้องทางไวยากรณ์เนื่องจากชื่อตัวแปรไม่สามารถขึ้นต้นด้วยตัวเลข
Nico Haase

0

หากคุณมักจะส่งผ่านค่าที่ 8 คุณสามารถจัดลำดับพารามิเตอร์ของคุณใหม่เพื่อให้เป็นค่าแรก คุณจะต้องระบุพารามิเตอร์จนถึงค่าสุดท้ายที่คุณต้องการตั้งค่า

หากคุณใช้ค่าที่แตกต่างกันคุณมี 2 ตัวเลือก

หนึ่งคือการสร้างชุดของฟังก์ชัน wrapper ที่ใช้พารามิเตอร์ที่แตกต่างกันและตั้งค่าเริ่มต้นให้กับฟังก์ชันอื่น ๆ สิ่งนี้มีประโยชน์หากคุณใช้ชุดค่าผสมเพียงเล็กน้อย แต่อาจทำให้ยุ่งได้อย่างรวดเร็ว

ตัวเลือกอื่นคือการส่งอาร์เรย์โดยที่คีย์เป็นชื่อของพารามิเตอร์ จากนั้นคุณสามารถตรวจสอบว่ามีค่าในอาร์เรย์ด้วยคีย์หรือไม่และหากไม่ใช้ค่าเริ่มต้น แต่อีกครั้งอาจทำให้ยุ่งและเพิ่มโค้ดพิเศษจำนวนมากหากคุณมีพารามิเตอร์จำนวนมาก


0

PHP อนุญาตให้อาร์กิวเมนต์เริ่มต้น ( ลิงค์ ) ในกรณีของคุณคุณสามารถกำหนดพารามิเตอร์ทั้งหมดตั้งแต่ 3 ถึง 8 เป็น NULL หรือเป็นสตริงว่าง "" ขึ้นอยู่กับโค้ดฟังก์ชันของคุณ ด้วยวิธีนี้คุณสามารถเรียกใช้ฟังก์ชันได้โดยใช้พารามิเตอร์สองตัวแรกเท่านั้น

ตัวอย่างเช่น:

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

ความคิดที่น่าสนใจ ... อย่างไรก็ตามข้อเสนอของคุณไม่สามารถแก้ปัญหาได้ ในความเป็นจริงหากคุณเพิ่มข้อมูลเกี่ยวกับอาร์กิวเมนต์ใดที่ถูกสะท้อน (เช่นโดยการใช้echo " this is arg3: " . $arg3;ฯลฯ คุณจะเห็นว่าการเรียกเช่นyourFunction(3, 2, $arg8=5);จะพิมพ์32 this is arg3: 5ปัญหาคือตำแหน่งพารามิเตอร์ยังคงมีความสำคัญเมื่อส่งผ่านพารามิเตอร์ทางเลือกใน PHP ... ชื่อพารามิเตอร์ไม่เพียงพอที่จะจับคู่ค่าพารามิเตอร์กับชื่อพารามิเตอร์
mastropi

0

เพียงตั้งค่า Null เพื่อละเว้นพารามิเตอร์ที่คุณไม่ต้องการใช้จากนั้นตั้งค่าพารามิเตอร์ที่ต้องการตามตำแหน่ง

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.