24

PHP 関数 foo があるとします。

function foo($firstName = 'john', $lastName = 'doe') {
    echo $firstName . " " . $lastName;
}
// foo(); --> john doe

2 番目のオプション パラメータのみを指定する方法はありますか?

例:

foo($lastName='smith'); // output: john smith
4

13 に答える 13

34

PHPは、関数自体の名前付きパラメーターをサポートしていません。ただし、これを回避する方法はいくつかあります。

  1. 関数の唯一の引数として配列を使用します。次に、配列から値を取得できます。これにより、配列で名前付き引数を使用できます。
  2. コンテキストに応じてオプションの数の引数を許可する場合は、関数定義で有効なパラメーターを指定する代わりに、func_num_argsおよびfunc_get_argsを使用できます。次に、引数の数、文字列の長さなどに基づいて、何をすべきかを決定できます。
  3. 指定したくない引数にnull値を渡します。実際には回避できませんが、機能します。
  4. オブジェクトコンテキストで作業している場合は、マジックメソッド__call()を使用してこれらのタイプのリクエストを処理できるため、渡された引数に基づいてプライベートメソッドにルーティングできます。
于 2009-03-27T17:08:49.340 に答える
23

デフォルト値をより簡単に設定できる配列手法のバリエーション:

function foo($arguments) {
  $defaults = array(
    'firstName' => 'john',
    'lastName' => 'doe',
  );

  $arguments = array_merge($defaults, $arguments);

  echo $arguments['firstName'] . ' ' . $arguments['lastName'];
}

使用法:

foo(array('lastName' => 'smith')); // output: john smith
于 2009-03-27T17:29:09.120 に答える
9

コードを少しリファクタリングできます。

function foo($firstName = NULL, $lastName = NULL)
{
    if (is_null($firstName))
    {
        $firstName = 'john';
    }
    if (is_null($lastName ))
    {
        $lastName = 'doe';
    }

    echo $firstName . " " . $lastName;
}

foo(); // john doe
foo('bill'); // bill doe
foo(NULL,'smith'); // john smith
foo('bill','smith'); // bill smith
于 2009-03-27T17:48:20.430 に答える
6

複数のオプションのパラメーターがある場合、1つの解決策は、ハッシュ配列である単一のパラメーターを渡すことです。

function foo(array $params = array()) {
    $firstName = array_key_exists("firstName", $params) ?
      $params["firstName"] : "";
    $lastName = array_key_exists("lastName", $params) ?
      $params["lastName"] : "";
    echo $firstName . " " . $lastName;
}

foo(['lastName'=>'smith']);

もちろん、このソリューションでは、ハッシュ配列のフィールドが存在するか、スペルが正しいかどうかの検証はありません。検証するのはあなた次第です。

于 2009-03-27T17:09:33.190 に答える
3

あなたが望む方法:いいえ。

NULLなどの特別なマークを使用して、値が指定されていないことに注意することができます。

function foo($firstName, $lastName = 'doe') {
    if (is_null($firstName))
        $firstName = 'john';
    echo $firstName . " " . $lastName;
}

foo(null, 'smith');
于 2009-03-27T17:08:09.903 に答える
3

いいえ。これを行う通常の方法は、文字列の長さ、入力などのように、どのパラメーターが暗示されているかを判断するヒューリスティックを使用することです。

一般的に言えば、最も必要なものから最も必要のないものへの順序でパラメーターを取得する関数を作成します。

于 2009-03-27T17:02:45.733 に答える
2

2.5年前にPHPを使い始めたとき、このソリューションがSOにあったことを願っています。私が作成した例ではうまく機能しますが、完全に拡張可能であってはならない理由がわかりません。以前に提案されたものに比べて、次の利点があります。

(i) 関数内のパラメーターへのすべてのアクセスは、配列アクセスを要求するのではなく、パラメーターが完全に宣言されているかのように、名前付き変数によって行われます。

(ii) 既存の機能を非常に迅速かつ簡単に適応させることができる

(iii) どの関数に対しても 1 行の追加コードしか必要ありません (関数シグネチャで行う既定のパラメーターを定義するという避けられない必要性に加えて、代わりにそれらを配列で定義します)。追加の行の功績は完全に Bill Karwin によるものです。この行は、すべての関数で同じです。

方法

必須パラメーターとオプションの配列を使用して関数を定義します

オプションのパラメータをローカル変数として宣言します

重要なのは、配列を介して渡したものを使用して、オプションのパラメーターの事前に宣言されたデフォルト値を置き換えることです。

extract(array_merge($arrDefaults, array_intersect_key($arrOptionalParams, $arrDefaults)));

関数を呼び出して、その必須パラメーターを渡し、必要なオプションのパラメーターのみを渡します

例えば、

function test_params($a, $b, $arrOptionalParams = array()) {

$arrDefaults = array('c' => 'sat',

                     'd' => 'mat');

extract(array_merge($arrDefaults, array_intersect_key($arrOptionalParams, $arrDefaults)));

echo "$a $b $c on the $d";

}

そして、このように呼び出します

test_params('The', 'dog', array('c' => 'stood', 'd' => 'donkey'));
test_params('The', 'cat', array('d' => 'donkey'));
test_params('A', 'dog', array('c' => 'stood'));

結果:

犬はロバの上に立った

猫はロバの上に座った

犬がマットの上に立っていた

于 2015-08-19T14:54:28.770 に答える
1

引数は位置順に渡す必要があります。パラメータ自体をスキップすることはできません。スキップするには、デフォルトのパラメーター値を指定する必要があります。おそらく、それはあなたが達成しようとしている目的を無効にします。

パラメーターを別の方法で受け入れるように関数を書き直すことなく、これを回避する呼び出し時の方法を次に示します。

$func = 'foo';
$args = ['lastName' => 'Smith'];

$ref = new ReflectionFunction($func);
$ref->invokeArgs(array_map(function (ReflectionParameter $param) use ($args) {
    if (array_key_exists($param->getName(), $args)) {
        return $args[$param->getName()];
    }
    if ($param->isOptional()) {
        return $param->getDefaultValue();
    }
    throw new InvalidArgumentException("{$param->getName()} is not optional");
}, $ref->getParameters()));

つまり、リフレクションを使用して関数のパラメーターを検査し、それらを名前で使用可能なパラメーターにマップし、オプションのパラメーターをデフォルト値でスキップします。はい、これは醜くて面倒です。このサンプルを使用して、次のような関数を作成できます。

call_func_with_args_by_name('foo', ['lastName' => 'Smith']);
于 2015-08-26T09:11:41.407 に答える
0

悲しいことに、あなたがやろうとしていることには、それを行うための「シンタックスシュガー」の方法がありません。それらはすべてさまざまな形式のWTFです。

未定義の数の任意のパラメーターを受け取る関数が必要な場合は、

function foo () { 
     $args = func_get_args(); 
     # $args = arguments in order 
}

トリックを行います。PHPの場合、これは少し魔法のような側面であるため、使いすぎないようにしてください。

次に、オプションでデフォルトを適用し、パラメータ数に基づいて奇妙なことを行うことができます。

function foo() { 
   $args = func_get_args();
   if (count($args) < 1 ) { 
       return "John Smith"; 
   }
   if (count($args) < 2 ) { 
       return "John " . $args[0];
   }
   return $args[0] . " " . $args[1];
}

また、オプションでPerlスタイルのパラメータをエミュレートすることもできます。

function params_collect($arglist){ 
    $config = array();
    for ($i = 0; $i < count($arglist); $i+=2) { 
        $config[$i] = $config[$i+1];
    }
    return $config; 
}
function param_default($config, $param, $default){ 
    if (!isset($config[$param])) { 
        $config[$param] = $default;
    }
    return $config;
}

function foo() { 
   $args = func_get_args();
   $config = params_collect($args); 
   $config = param_default($config, 'firstname', 'John'); 
   $config = param_default($config, 'lastname', 'Smith'); 
   return $config['firstname'] . ' ' . $config['lastname'];   
}

foo('firstname', 'john', 'lastname', 'bob'); 
foo('lastname', 'bob', 'firstname', 'bob'); 
foo('firstname', 'smith'); 
foo('lastname', 'john');

もちろん、ここでは配列引数を使用するが簡単ですが、物事を行うための選択肢(悪い方法でも)が許可されています。

注目すべきことに、これはfoo(firstname =>'john');だけを実行できるため、Perlの方が優れています。

于 2009-03-27T17:11:47.147 に答える
-1

いいえ、ありませんが、配列を使用できます。

function foo ($nameArray) {
    // Work out which values are missing?
    echo $nameArray['firstName'] . " " . $nameArray['lastName'];
}

foo(array('lastName'=>'smith'));
于 2009-03-27T17:09:55.607 に答える