web-dev-qa-db-ja.com

関数呼び出しでオプションの引数をスキップするにはどうすればよいですか?

OK、PHPで引数をスキップする方法を完全に忘れました。

私が持っているとしましょう:

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

中央のパラメーターがデフォルト値(つまり '50')になるように、この関数をどのように呼び出すのでしょうか?

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

上記は正しいでしょうか?これを機能させることはできません。

84
Sebastian

あなたの投稿は正しいです。

残念ながら、パラメーターリストの最後にオプションのパラメーターを使用する必要がある場合は、その最後のパラメーターまですべてを指定する必要があります。通常、ミックスアンドマッチを行う場合は、''またはnullのデフォルト値を指定し、それらがデフォルト値である場合は関数内で使用しないでください。

49
zombat

falsenullのようなデフォルトを指定する以外に、引数を「スキップ」する方法はありません。

これについては、PHPには構文上の砂糖が欠けているため、次のようなものがよく表示されます。

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

コメントで雄弁に言ったように、これは名前付き引数をエミュレートするために配列を使用しています。

これにより、究極の柔軟性が得られますが、場合によっては必要ありません。少なくとも、予想されていないと思われるものはほとんど、引数リストの最後に移動できます。

37

いいえ、この方法で引数をスキップすることはできません。引数がパラメータリストの最後にある場合、引数の受け渡しonlyを省略できます。

これについての公式提案がありました: https://wiki.php.net/rfc/skipparams 、これは拒否されました。提案ページは、このトピックに関する他のSO質問にリンクしています。

35
Cristik

オプションの引数をスキップできることに関しては何も変わっていませんが、正しい構文とスキップしたい引数に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');および将来関数を呼び出す人は、毎回デフォルトまたはそれらのために宣言された定数を覚える必要はありません。

5
Ibrahim Lawal

簡単な答えはNoです。しかし、なぜ引数を再配置してこれが達成されるのにスキップするのでしょうか?

あなたのものは「デフォルトの関数引数の不適切な使用法」であり、期待通りに動作しません。

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"

デフォルトを非デフォルトの後に右側に置くと、定義されていない/指定されている場合、その変数のデフォルト値が常に再調整されます。ここに参照用の link があります。

編集:他の人が提案しているようにnullに設定すると動作する可能性があり、別の選択肢ですが、あなたが望むものに適していない可能性があります。定義されていない場合、デフォルトは常にnullに設定されます。

4
Nelson Owalo

引数をスキップすることはできませんが、配列パラメーターを使用でき、パラメーターの配列であるパラメーターを1つだけ定義する必要があります。

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

また、必要な数のパラメーターを追加できますが、定義する必要はありません。関数を呼び出すとき、次のようにパラメーターを配置します。

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

スキップされたパラメーターについては、安全のためにデフォルトのパラメーターを使用する必要があります。

(デフォルトのパラメーターが ''または同様の場合、またはその逆の場合、nullに設定すると問題が発生します...)

2
Frank Nocke

上記のように、パラメーターをスキップすることはできません。私はこの回答を書いて、コメントに入れるには大きすぎる補遺を提供しました。

@Frank Nocke proposes デフォルトのパラメーターで関数を呼び出すため、たとえば

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

あなたは使うべきです

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

機能的には、最初の2つの(_$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
Voitcus

前述のとおり 、何も変更されていません。ただし、あまりにも多くのパラメーター(特にオプションのパラメーター)がコードのにおいを強く示していることに注意してください。

おそらくあなたの機能はやり過ぎです:

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

(これは、あまり正式ではない parameter arrayテクニックの栄光版です

パラメーターをオプションにする理由が間違っている場合があります。この例では、$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
RandomSeed

制限をnullに設定します

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

そしてその関数を呼び出す

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

制限を設定する場合は、引数として渡すことができます

getData('some name', 50, '23');
0
Hari Kumar

このスニペット:

 
 function getData($ name、$ options){
 $ default = array(
 'limit' => 50、
 'page' => 2、
); 
 $ args = array_merge($ default、$ options); 
 print_r($ args); 
} 
 
 getData( 'foo'、array()); 
 getData( 'foo'、array( 'limit' => 2)); 
 getData( 'foo'、array ( 'limit' => 10、 'page' => 10)); 
 

答えは:

 
 Array 
(
 [limit] => 50 
 [page] => 2 
)
 Array 
(
 [limit] => 2 
 [page] => 2 
)
 Array 
(
 [limit] => 10 
 [page] => 10 
)
 
0
nobody0day

これは、技術的に有能な回答が数多くある古い質問ですが、PHPの最新の設計パターンの1つであるオブジェクト指向プログラミングを求めています。プリミティブスカラーデータ型のコレクションを注入する代わりに、関数に必要なすべてのデータを含む「注入オブジェクト」の使用を検討してください。 http://php.net/manual/en/language.types.intro.php

挿入されたオブジェクトには、プロパティ検証ルーチンなどがあります。挿入されたオブジェクトへのデータのインスタンス化と挿入がすべての検証に合格できない場合、コードはすぐに例外をスローし、アプリケーションは扱いにくいプロセスを回避できます潜在的に不完全なデータ。

展開する前に、インジェクトされたオブジェクトを入力して、ミスをキャッチできます。数年前のいくつかのアイデアがこの記事にまとめられています。

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

0
Ray Paseur

これは私がすることです:

<?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であなたが望むことはできません。

ただし、次のコードを関数の先頭に配置して、機能を取得できます。

_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
Rizier123