함수 호출에서 선택적 인수를 어떻게 건너 뛰나요?


94

좋아, PHP에서 인수를 건너 뛰는 방법을 완전히 잊었습니다.

내가 가지고 있다고 가정 해 봅시다.

function getData($name, $limit = '50', $page = '1') {
    ...
}

중간 매개 변수가 기본값 (예 : '50')을 사용하도록이 함수를 어떻게 호출합니까?

getData('some name', '', '23');

위의 내용이 맞습니까? 나는 이것을 작동시킬 수없는 것 같다.


1
@ 척 정확히 무엇을 찾고 있습니까? 해결 방법이나 클래스처럼 이것을 구현하거나 ...?
Rizier123 2015 년

@ Rizier123 현재 PHP 버전이 다른 언어와 마찬가지로 인수 건너 뛰기를 지원하는지 확인하려고합니다. 현재 답변이 오래되었을 수 있습니다. 현상금 설명에서 : "현재 답변은 5 년 전입니다. 현재 버전의 PHP가 변경됩니까?"
Chuck Le Butt

1
@Chuck 그러면 대답은 아마 다음과 같을 것입니다. 해결 방법 / 코드가 없으면 기능을 사용할 수 없습니다.
Rizier123

여기의 모든 답변은 호출되는 함수를 제어 할 수 있다고 가정하는 것 같습니다. 해당 함수가 라이브러리 또는 프레임 워크의 일부인 경우 인수 3이 필요한 경우 인수 2에 대해 무언가를 지정하는 것 외에는 옵션이 없습니다. 유일한 옵션은 함수의 소스를 찾고 기본값을 복제하는 것입니다.
Snapey

건너 뛸 수는 없지만을 사용하여 기본 인수를 전달할 수 있습니다 ReflectionFunction. 비슷한 질문 에 그 답변 을 게시했습니다 .
David

답변:


55

귀하의 게시물이 정확합니다.

불행히도 매개 변수 목록의 맨 끝에 선택적 매개 변수를 사용해야하는 경우 마지막 매개 변수까지 모든 것을 지정해야합니다. 일반적으로 당신이 앤 매치를 혼합하려는 경우, 당신은 그들에게의 디폴트 값을 제공 ''또는 null, 그들은 그 기본값 경우 함수 내에서 사용하지 않습니다.


1
예를 들어 줄 수 있습니까?
나는 나입니다

2
@iamme는 할 $limit = is_numeric($limit) ? $limit : '50';의 시작 부분에 GetData의의 기능
Kamafeather

40

false또는 과 같은 기본값을 지정하는 것 외에 다른 인수를 "건너 뛰는"방법은 없습니다 null.

PHP에는 이와 관련하여 구문상의 설탕이 부족하기 때문에 다음과 같은 내용이 자주 표시됩니다.

checkbox_field(array(
    'name' => 'some name',
    ....
));

주석에서 웅변 적으로 말했듯이 배열을 사용하여 명명 된 인수를 에뮬레이트합니다.

이는 궁극적 인 유연성을 제공하지만 경우에 따라 필요하지 않을 수 있습니다. 적어도 대부분의 경우 예상하지 못한 것으로 생각되는 모든 항목을 인수 목록의 끝으로 이동할 수 있습니다.


2
나는 '이와 같은 것'을 '배열을 사용하여 명명 된 인수를 에뮬레이트하기', FWIW로 식별합니다. :)
혼돈

3
더 유연함에도 불구하고 설정해야하거나 설정할 수있는 매개 변수를 기억해야합니다 (서명에 포함되어 있지 않기 때문에). 따라서 결국에는보기만큼 유용하지 않을 수도 있지만 물론 이것은 상황에 따라 다릅니다.
Felix Kling

그렇다면 그러한 시나리오에 대한 모범 사례는 무엇일까요?
Adam Grant

39

아니요, 이런 식으로 인수를 건너 뛸 수 없습니다. 매개 변수 목록의 끝에있는 경우 에만 인수 전달을 생략 할 수 있습니다 .

이에 대한 공식적인 제안이있었습니다 : https://wiki.php.net/rfc/skipparams , 거절당했습니다. 제안 페이지는이 주제에 대한 다른 SO 질문으로 연결됩니다.


그렇다면 PHP 함수는 어떻게 더 많거나 적은 매개 변수를 선택적으로 가질 수 있습니까?
나는 나입니다

2
PHP는 기본 매개 변수 값을 지원합니다. 그러나 이러한 매개 변수는 목록의 끝에 있어야합니다.
Cristik

1
당신은에서 예를 찾을 수 있습니다 PHP 문서를
Cristik

2
바보들. 나를 너무 화나게 만든다. 다른 사람이 요청한 기능이 마음에 들지 않으면 사용하지 마십시오. 인터넷은 때때로 최악입니다.
Lee Saxon

@LeeSaxon 문제는 가독성과 이식성입니다. 1) 누군가 매개 변수를 건너 뛰기로 결정하고 코드를 디버깅하는 누군가가이 사실을 놓치면 큰 혼란이 발생합니다. 2) 새로운 코드는 중대한 오버홀 없이는 이전 버전에서 작동 할 수 없으며 실수 가능성이 매우 높습니다.
Mark Walsh

6

선택적 인수를 건너 뛸 수 있다는 점에 대해서는 아무것도 변경되지 않았지만 올바른 구문과 건너 뛰려는 인수에 대해 NULL을 지정할 수 있도록하려면 다음 방법을 사용하십시오.

define('DEFAULT_DATA_LIMIT', '50');
define('DEFAULT_DATA_PAGE', '1');

/**
 * getData
 * get a page of data 
 *
 * Parameters:
 *     name - (required) the name of data to obtain
 *     limit - (optional) send NULL to get the default limit: 50
 *     page - (optional) send NULL to get the default page: 1
 * Returns:
 *     a page of data as an array
 */

function getData($name, $limit = NULL, $page = NULL) {
    $limit = ($limit===NULL) ? DEFAULT_DATA_LIMIT : $limit;
    $page = ($page===NULL) ? DEFAULT_DATA_PAGE : $page;
    ...
}

이렇게 getData('some name',NULL,'23');호출 할 수 있습니다. 앞으로 함수를 호출하는 사람은 매번 기본값이나 선언 된 상수를 기억할 필요가 없습니다.


1
당신은 아마 엄격한 비교 ($ 한계 === null)와 싶어
roelleor

4

간단한 대답은 아니오 입니다. 그러나 인수를 재정렬 할 때이를 건너 뛰는 이유는 무엇입니까?

귀하는 " 기본 함수 인수의 잘못된 사용 "이며 예상대로 작동하지 않습니다.

PHP 문서의 추가 정보 :

기본 인수를 사용할 때 모든 기본값은 기본값이 아닌 인수의 오른쪽에 있어야합니다. 그렇지 않으면 예상대로 작동하지 않습니다.

다음을 고려하세요:

function getData($name, $limit = '50', $page = '1') {
    return "Select * FROM books WHERE name = $name AND page = $page limit $limit";
}

echo getData('some name', '', '23');   // won't work as expected

출력은 다음과 같습니다.

"Select * FROM books WHERE name = some name AND page = 23 limit"

기본 함수 인수의 올바른 사용법은 다음과 같아야합니다.

function getData($name, $page = '1', $limit = '50') {
    return "Select * FROM books WHERE name = $name AND page = $page limit $limit";
}

echo getData('some name', '23');  // works as expected

출력은 다음과 같습니다.

"Select * FROM books WHERE name = some name AND page = 23 limit 50"

기본값이 아닌 다음 오른쪽에 기본값을두면 해당 변수가 정의 /주지되지 않은 경우 항상 해당 변수의 기본값을 되돌릴 수 있습니다. 여기에 링크가 있습니다. 있습니다. 참조 용 와 해당 예제의 출처가 여기에 있습니다.

편집 : null다른 사람들이 제안한대로 설정하면 작동 할 수 있으며 또 다른 대안이지만 원하는 것에 적합하지 않을 수 있습니다. 정의되지 않은 경우 항상 기본값을 null로 설정합니다.


명확하게 설명 된 구문 설명을 제공하므로 이것이 가장 좋은 대답입니다! 감사합니다!
Christian

2

건너 뛴 매개 변수에 대해서는 기본 매개 변수를 사용하여 안전을 유지하십시오.

(기본 매개 변수가 ''또는 이와 유사하거나 그 반대 인 경우 null로 설정하면 문제가 발생합니다 ...)


2

위에서 언급했듯이 매개 변수를 건너 뛸 수 없습니다. 나는 주석을 달기에 너무 큰 부록을 제공하기 위해이 답변을 작성했습니다.

@Frank Nocke 는 기본 매개 변수를 사용하여 함수를 호출하도록 제안 합니다.

function a($b=0, $c=NULL, $d=''){ //...

당신은 사용해야합니다

$var = a(0, NULL, 'ddd'); 

기능적으로 처음 두 개를 생략하는 것과 동일합니다 ( $b$c ) 매개 변수 합니다.

어떤 것이 기본값인지는 확실하지 않습니다. 0 을 제공하기 위해 입력 했습니까, 아니면 중요합니까?).

또한 함수 (또는 메소드) 작성자가 기본값을 변경할 수있는 경우 기본값 문제가 외부 (또는 내장) 함수와 연결될 위험이 있습니다. 따라서 프로그램에서 호출을 변경하지 않으면 의도하지 않게 동작을 변경할 수 있습니다.

일부 해결 방법은 다음과 같은 일부 전역 상수를 정의하는 것입니다. DEFAULT_A_B "함수 A의 B 매개 변수의 기본값"및 "생략"매개 변수와 하는 것입니다.

$var = a(DEFAULT_A_B, DEFAULT_A_C, 'ddd');

클래스의 경우 클래스 상수를 정의하면 더 쉽고 우아합니다. 예를 들어 전역 범위의 일부이기 때문입니다.

class MyObjectClass {
  const DEFAULT_A_B = 0;

  function a($b = self::DEFAULT_A_B){
    // method body
  }
} 
$obj = new MyObjectClass();
$var = $obj->a(MyObjectClass::DEFAULT_A_B); //etc.

이 기본 상수는 코드 전체에서 정확히 한 번 정의되므로 (메서드 선언에도 값이 없음) 예기치 않은 변경이 발생하는 경우 항상 올바른 기본값으로 함수 / 메서드를 제공합니다.

물론이 솔루션의 명확성은 원시 기본값 (예 : NULL,0 독자에게 아무 말도하지 않는 등)을 .

(같은 전화 $var = a(,,'ddd');가 최선의 선택이 될 것이라는 데 동의합니다 )


2

인수를 건너 뛸 수는 없지만 배열 매개 변수를 사용할 수 있으며 매개 변수 배열 인 1 개의 매개 변수 만 정의하면됩니다.

function myfunction($array_param)
{
    echo $array_param['name'];
    echo $array_param['age'];
    .............
}

또한 필요한만큼의 매개 변수를 추가 할 수 있으며 정의 할 필요가 없습니다. 함수를 호출 할 때 다음과 같이 매개 변수를 입력합니다.

myfunction(array("name" => "Bob","age" => "18", .........));

0

다른 모든 사람들이 이미 말했듯이 함수에 코드 줄을 추가하지 않고는 PHP에서 원하는 것이 가능하지 않을 것이라고 말했습니다.

그러나이 코드 조각을 함수 맨 위에 배치하여 기능을 얻을 수 있습니다.

foreach((new ReflectionFunction(debug_backtrace()[0]["function"]))->getParameters() as $param) {
    if(empty(${$param->getName()}) && $param->isOptional())
        ${$param->getName()} = $param->getDefaultValue();
}

따라서 기본적 debug_backtrace()으로이 코드가 배치 된 함수 이름을 얻은 다음 새 ReflectionFunction개체 를 만들고 모든 함수 인수를 반복합니다.

루프에서 함수 empty()인수가 "선택 사항" 인지 확인하기 만하면됩니다 (기본값이 있음을 의미). 그렇다면 단순히 기본값을 인수에 할당합니다.

Demo


0

제한을 null로 설정

function getData($name, $limit = null, $page = '1') {
    ...
}

그 함수를 호출

getData('some name', null, '23');

제한을 설정하려면 인수로 전달할 수 있습니다.

getData('some name', 50, '23');

0

앞서 언급 했듯이 아무것도 변경되지 않았습니다. 그러나 너무 많은 매개 변수 (특히 선택적 매개 변수)는 코드 냄새의 강력한 지표입니다.

아마도 당신의 기능이 너무 많은 일을하고있을 것입니다 :

// first build context
$dataFetcher->setPage(1);
// $dataFetcher->setPageSize(50); // not used here
// then do the job
$dataFetcher->getData('some name');

일부 매개 변수는 논리적으로 그룹화 될 수 있습니다.

$pagination = new Pagination(1 /*, 50*/);
getData('some name', $pagination);
// Java coders will probably be familiar with this form:
getData('some name', new Pagination(1));

마지막 수단으로 언제든지 임시 매개 변수 객체를 도입 할 수 있습니다 .

$param = new GetDataParameter();
$param->setPage(1);
// $param->setPageSize(50); // not used here
getData($param);

(이는 덜 형식적인 매개 변수 배열 기법 의 미화 버전 일뿐입니다 )

때로는 매개 변수를 선택적으로 만드는 바로 그 이유가 잘못되었습니다. 이 예에서 $page정말 선택 사항입니까? 몇 개의 문자를 저장하는 것이 실제로 효과가 있습니까?

// dubious
// it is not obvious at first sight that a parameterless call to "getData()"
// returns only one page of data
function getData($page = 1);

// this makes more sense
function log($message, $timestamp = null /* current time by default */);

0

이 스 니펫 :

    function getData ($ name, $ options) {
       $ default = 배열 ​​(
            '한도'=> 50,
            '페이지'=> 2,
        );
        $ args = array_merge ($ default, $ options);
        print_r ($ args);
    }

    getData ( 'foo', array ());
    getData ( 'foo', array ( 'limit'=> 2));
    getData ( 'foo', array ( 'limit'=> 10, 'page'=> 10));

대답은 다음과 같습니다.

     정렬
    (
        [한도] => 50
        [페이지] => 2
    )
    정렬
    (
        [한도] => 2
        [페이지] => 2
    )
    정렬
    (
        [한도] => 10
        [페이지] => 10
    )


2
좋은. 그러나 약간의 설명이 도움이 될 것입니다.
showdev

좋은 대답이지만 선택적 매개 변수를 생략하려면 다음과 같이하십시오. function getData ($ name, $ args = array ()) {$ defaults = array ( 'limit': => 50, 'page'=> 2) ; $ args = array_merge ($ defaults, $ args); } 이제 다음과 같이 첫 번째 매개 변수로만이 함수를 호출 할 수 있습니다. getData ( 'foo');
EchoSin

0

이것이 내가 할 일입니다.

<?php

    function getData($name, $limit = '', $page = '1') {
            $limit = (EMPTY($limit)) ? 50 : $limit;
            $output = "name=$name&limit=$limit&page=$page";
            return $output;
    }

     echo getData('table');

    /* output name=table&limit=50&page=1 */

     echo getData('table',20);

    /* name=table&limit=20&page=1 */

    echo getData('table','',5);

    /* output name=table&limit=50&page=5 */

    function getData2($name, $limit = NULL, $page = '1') {
            $limit = (ISSET($limit)) ? $limit : 50;
            $output = "name=$name&limit=$limit&page=$page";
            return $output;
    }

    echo getData2('table');

    // /* output name=table&limit=50&page=1 */

    echo getData2('table',20);

    /* output name=table&limit=20&page=1 */

    echo getData2('table',NULL,3);

    /* output name=table&limit=50&page=3 */

?>

이것이 누군가를 도울 수 있기를 바랍니다.


0

이것은 기술적으로 유능한 답변이 많은 오래된 질문이지만, PHP의 현대적인 디자인 패턴 중 하나 인 객체 지향 프로그래밍에 대해 외칩니다. 원시 스칼라 데이터 유형의 모음을 삽입하는 대신 함수에 필요한 모든 데이터를 포함하는 "주입 된 객체"를 사용하는 것이 좋습니다. http://php.net/manual/en/language.types.intro.php

주입 된 개체에는 속성 유효성 검사 루틴 등이있을 수 있습니다. 주입 된 개체에 대한 데이터의 인스턴스화 및 주입이 모든 유효성 검사를 통과 할 수없는 경우 코드는 즉시 예외를 throw 할 수 있으며 애플리케이션은 처리의 어색한 프로세스를 피할 수 있습니다. 잠재적으로 불완전한 데이터로.

주입 된 개체를 입력하여 배포하기 전에 실수를 포착 할 수 있습니다. 이 기사에는 몇 년 전의 아이디어 중 일부가 요약되어 있습니다.

https://www.experts-exchange.com/articles/18409/Using-Named-Parameters-in-PHP-Function-Calls.html


0

선택적 매개 변수로 팩토리를 만들어야했는데 해결 방법은 null 병합 연산자를 사용하는 것입니다.

public static function make(
    string $first_name = null,
    string $last_name = null,
    string $email = null,
    string $subject = null,
    string $message = null
) {
    $first_name = $first_name ?? 'First';
    $last_name  = $last_name ?? 'Last';
    $email      = $email ?? 'foo@bar.com';
    $subject    = $subject ?? 'Some subject';
    $message    = $message ?? 'Some message';
}

용법:

$factory1 = Factory::make('First Name Override');
$factory2 = Factory::make(null, 'Last Name Override');
$factory3 = Factory::make(null, null, null, null 'Message Override');

가장 예쁜 것은 아니지만 테스트를 위해 공장에서 사용하기에 좋은 패턴 일 수 있습니다.


-1

이 시도.

function getData($name, $limit = NULL, $page = '1') {
               if (!$limit){
                 $limit = 50;
               }
}

getData('some name', '', '23');

-2

함수 호출에서 중간 매개 변수를 건너 뛸 수 없습니다. 그러나 다음과 같이 해결할 수 있습니다.

function_call('1', '2', '3'); // Pass with parameter.
function_call('1', null, '3'); // Pass without parameter.

함수:

function function_call($a, $b='50', $c){
    if(isset($b)){
        echo $b;
    }
    else{
        echo '50';
    }
}

$ c 외에 기본값이 필요한 이유가 무엇인지 잘 모르겠습니다 (선택 인수 뒤에는 필수 인수를 가질 수 없습니다).
Frank Forte

-2

@IbrahimLawal이 지적했듯이. null값으로 설정하는 것이 가장 좋습니다 . 전달 null된 값이 정의 된 기본값을 사용 하는지 확인 하십시오.

<?php
define('DEFAULT_LIMIT', 50);
define('DEFAULT_PAGE', 1);

function getData($name, $limit = null, $page = null) {
    $limit = is_null($limit) ? DEFAULT_LIMIT : $limit;
    $page = is_null($page) ? DEFAULT_PAGE : $page;
    ...
}
?>

도움이 되었기를 바랍니다.


당신은 단순히 응답을 복제했습니다. 오히려 당신은 그것에 찬성하거나 댓글을 달 수 있습니다.
Ibrahim Lawal

-6
getData('some name');

전달하지 않으면 기본값이 허용됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.