선택적 매개 변수가있는 PHP 함수


107

10 개의 매개 변수를받을 수있는 PHP 함수를 작성했지만 2 개만 필요합니다. 때로는 8 번째 매개 변수를 정의하고 싶지만 8 번째에 도달 할 때까지 각 매개 변수에 대해 빈 문자열을 입력하고 싶지 않습니다.

내가 가진 한 가지 아이디어는 실제 함수에 전달하는 매개 변수 배열로 추상화 된 함수를 전달하는 것이 었습니다.

원하는 매개 변수 만 전달할 수 있도록 함수를 설정하는 더 좋은 방법이 있습니까?



이상하다. PHP의 내장 함수는 선택적 매개 변수를 가질 수 있습니다. 그렇다면 왜 그런 함수를 만들 수 없습니까?
Rodrigo

2
참고 이러한 답변의 대부분은 구식이 ... PHP는 이제 지원 과 기능 가변 길이 인수 목록을 .
ashleedawg

답변:


62

함수가 하나의 매개 변수 인 배열을 취하도록합니다. 실제 매개 변수를 배열의 값으로 전달하십시오.


편집 : Pekka의 의견에있는 링크가 요약합니다.


1
이상하다. PHP의 내장 함수는 선택적 매개 변수를 가질 수 있습니다. 그렇다면 왜 그런 함수를 만들 수 없습니까?
Rodrigo

1
@Rodrigo와 같은 기능을 정의하는 것은 절대적으로 가능합니다. 그러나 단일 선택적 매개 변수를 넘어서는 것은 매우 형편없는 위치 선택 사항입니다.
Matt Ball

1
좋아, 나는 []로 시도하고 있었다. 이제 나는 그것을하는 방법을 여기에서 본다 : stackoverflow.com/a/34869/1086511
Rodrigo

"배열 사용"제안만으로 할 수있는 것이 더 많습니다 . 비슷한 질문에 대한 Walf의 답변 과 동일한 스레드에서 더 심층적 인 예제를
살펴보십시오

63

이 경우 내가 한 일은 배열을 전달하는 것입니다. 여기서 키는 매개 변수 이름이고 값은 값입니다.

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

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

예를 들어 $ optional이 함수 내에서 전역으로 설정 될 필요가 없습니까?
user481826 2010 년

1
글로벌? 아니..? 함수를 호출하기 전에 해당 배열을 만들고 전달합니다. 내 코드는 수행해야 할 작업에 대한 Matt Balls 설명의 예입니다.
Rabbott

"배열 사용"제안
만하는 것 외에

45

원하는 것을 달성하려면 Rabbot이 말한 것처럼 배열을 사용하십시오 (과도하게 사용하면 문서화 / 유지 관리가 어려울 수 있음). 또는 전통적인 선택적 인수를 사용하십시오.

//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 년에는 '코드 냄새', '리팩토링'또는 '코드 유지 관리'와 같은 개념이 커뮤니티에서 인기가 없었습니다. 당신은 우리 대부분보다 먼저 한 발을
내디뎠습니다.

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

기본값을 null로 설정할 수 있습니다.

<?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 이하에서는 다음 두 가지 방법 중 하나를 사용하여이를 수행 할 수 있습니다.

  • 은 USING 는 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
여기에 이중 "="가 필요합니다. 그렇지 않으면 모든 표현식이 true를 반환합니다. 또한 두 번째 예제의 표현식은 변수가 항상 자신과 같기 때문에 항상 true를 반환합니다.
chuckieDub 2013 년

좋은 지적이지만 실제로 작동합니다. PHP에서이 코드 $x = null; if ($x) echo "true"; else echo "false";는 $ x var에 값이있는 경우에도 "false"를 출력합니다 (이 코드에서 "null"). 또한 두 방법 모두 삼항 연산자를 사용하므로 "="하나만 사용하는 것이 맞습니다. 로 테스트 method(); method(1); method(1, 2);하면 첫 번째 호출은 arg1과 arg2를 기본값과 연결하고 두 번째 호출은 두 번째 arg를 기본값과 연결하고 첫 번째 arg에 대해 "1"을 연결합니다. 마지막 호출은 기본값을 연결하지 않습니다.
Daniel Loureiro 2013 년

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

객체를 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!";
}

물론이 함수에서 "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

유효한 상태의 개체를 만드는 데 두 개의 값만 필요한 경우 다른 모든 선택적 인수를 제거하고 이에 대한 setter를 제공 할 수 있습니다 (런타임에 변경하지 않으려는 경우 제외). 그런 다음 두 개의 필수 인수로 개체를 인스턴스화하고 필요에 따라 setter를 통해 나머지를 설정합니다.

추가 읽기


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
더 자세히 설명해 주시겠습니까? 변수 이름은 숫자로 시작할 수 없기 때문에 주어진 코드는 구문, 무효
니코 하세을

0

일반적으로 8 번째 값만 전달하는 경우 첫 번째 값이되도록 매개 변수를 재정렬 할 수 있습니다. 설정하려는 마지막 매개 변수까지만 매개 변수를 지정하면됩니다.

다른 값을 사용하는 경우 두 가지 옵션이 있습니다.

하나는 다른 매개 변수를 사용하고 다른 매개 변수에 기본값을 설정하는 래퍼 함수 집합을 만드는 것입니다. 이것은 몇 가지 조합 만 사용하는 경우 유용하지만 매우 지저분해질 수 있습니다.

다른 옵션은 키가 매개 변수의 이름 인 배열을 전달하는 것입니다. 그런 다음 키가있는 배열에 값이 있는지 확인하고 기본값을 사용하지 않는 경우 확인할 수 있습니다. 그러나 다시 말하지만, 매개 변수가 많으면 더러워지고 추가 코드가 많이 추가 될 수 있습니다.


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;, 등 을 사용하여 eg를 호출하는 것을 볼 수 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.