2009-03-27 15 views
20

はのは、私はPHPの関数fooを持っているとしましょう:PHPで任意のパラメータ値を指定する方法はありますか?

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

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

例:これを行うための通常の方法は、などの文字列の長さ、タイピング、同様に、暗示されたパラメータを決定するためにいくつかの経験則である

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

答えて

32

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

  1. 関数の唯一の引数として配列を使用します。その後、配列から値を取り出すことができます。これにより、配列内の名前付き引数を使用できます。
  2. コンテキストに応じて任意の数の引数を許可する場合は、関数定義で有効なパラメータを指定するのではなく、func_num_argsおよびfunc_get_argsを使用できます。引数の数、文字列の長さなどに基づいて、何をすべきかを決定することができます。
  3. 指定しない引数にNULL値を渡します。実際にそれを回避していないが、それは動作します。
  4. オブジェクトコンテキストで作業している場合は、マジックメソッド__call()を使用してこれらのタイプのリクエストを処理し、どの引数が渡されたかに基づいてプライベートメソッドにルーティングできるようにすることができます。あなたは複数のオプションのパラメータを持っている場合
+0

暗黙のサポートはありませんが、受け入れられた回答よりも優れた回避策があります。下のWalfの解を参照してください。あなたが私の解決策でそれを必要とするかどうかについてもっと詳細があります(私は私が独立して到着したことを誓います)。 – DJDave

3

号は

は、一般的に言えば、あなたがしたいです最も必要なものから最も必要なものの順にパラメータを取る関数を書く。

+0

ヒューリスティックは、jQueryのように、パラメータがタイプによって間違いがないと確実に機能します。文字列の長さのような他の方法は、起こるのを待っている事故です。 – Walf

3

希望の方法:いいえ。

あなたは、その値が供給されていない注意することがNULLのように、いくつかの特別なマークを使用することができます。

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

foo(null, 'smith'); 
6

は、一つの解決策は、ハッシュ配列である単一のパラメータ渡すことです。このソリューションではもちろん

function foo(array $params = array()) { 
    echo $params['firstName'] . " " . $params['lastName']; 
} 

foo(array('lastName'=>'smith')); 

をハッシュ配列のフィールドその検証はありません存在するか、正しく綴られていますか?検証するのはあなた次第です。

+0

あなたはそれに私を打ち負かしました! – Teifion

-1

ありませんありませんが、あなたは、配列を使用できます:あなたが何をしようとして悲しいこと

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

foo(array('lastName'=>'smith')); 
+1

未設定の変数! –

+0

need => not = –

+0

おっと!私は数週間、PHPをコーディングしていない、あまりにも多くのPythonを使用している。 – Teifion

-1

はそれをやってのない「シンタックスシュガー」方法がありません。彼らはすべて様々な形態の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ではうまくいきます。

+0

自己への注意:PerlロジックをPHPに適用すると、事態が盛んになります。 Perlに固執し、振り返ることはありません。 –

21

デフォルト値を簡単に設定することができます、アレイ技術上の変化:

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 
+0

この$ defaultsとarray_mergeの定型文はすべて私のPHPコードの上にあります。 +1 – gnud

+1

連想配列の場合、 '$ arguments + = $ defaults;'はよりクリーンです。 – Walf

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 
+0

ありがとうございました。:)これはこれを行う最良の方法です,,,,他の誰もが盲目ですか? –

1

ここでは、いくつかの「オプション」スタイルの実装があります。あなたが標準としてそれらを使用する予定の場合、それまでのところ、非常に防弾ではありません。このパターンを試してみてください:

function some_func($required_parameter, &$optional_reference_parameter = null, $options = null) { 
    $options_default = array(
     'foo' => null, 
    ); 
    extract($options ? array_intersect_key($options, $options_default) + $options_default : $options_default); 
    unset($options, $options_default); 

    //do stuff like 
    if ($foo !== null) { 
     bar(); 
    } 
} 

これは、あなたの関数のローカル変数(ちょうど$fooこの例では)を与えるとデフォルトを持っていないすべての変数を作成しないように。これは、他のパラメータや関数内の他の変数を誤って上書きすることがないようにするためです。

1

私はこのソリューションが、2.5年前にPHPを使用し始めた時点であったと思います。私が作成した例ではうまくいきますが、なぜ完全に拡張できないのか分かりません。これは、以前に提案されているものに比べて以下の利点があります。

(I)関数内のパラメータへのすべてのアクセスのパラメータが完全ではなく、配列へのアクセスを必要とするよりも、宣言されたかのように、名前付き変数である

(ⅱ)それを(iii)既存の関数を非常に迅速かつ容易に適合させることができます。(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')); 
のようにそれを呼び出します

結果:

犬は猫がロバ

犬に座っロバ

に立った

+0

[その解決策は1.5年前であった。](0120-385-331) – Walf

+0

謝辞 - 私は2週間前にそれを見て、あなたにポイントを与えた。私が私の前に投稿する前に私はすべての "解決策"を再読しなかったと告白する。許可されている場合は、あなたの解決策を指している回答にコメントを追加します。 – DJDave

1

引数位置順にを渡す必要がマットの上に立って、あなたはパラメータごとにスキップすることはできませんse;それをスキップするには、デフォルトのパラメータ値を指定する必要があります。間違いなくあなたが達成しようとしているものの目的を破る。 、あなたは、関数のパラメータを検査し、それらをマッピングするためにリフレクションを使用している言い換えれば

$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']); 
+1

ベスト、関連性、正確な回答 – Offenso

0

:あなたは次のように関数を作成するために、このサンプルを使用することができますあなたも$のデフォルト値を変更することができ

function person($firstName = 'john', $lastName = 'doe') { 
    return $firstName . " " . $lastName; 
} 

function usualFirtNamedPerson($lastName = 'doe') { 
    return person('john', $lastName); 
} 

print(usualFirtNamedPerson('smith')); --> john smith 

注意をあなたが望むなら、プロセスの中の姓。

新しい関数がオーバーブローされていると推定される場合は、すべてのパラメータで関数を呼び出すだけです。より明確にしたい場合は、名前付き変数でリテラルをあらかじめ保存しておくか、コメントを使用することができます。

$firstName = 'Zeno'; 
$lastName = 'of Elea'; 
print(person($firstName, $lastName)); 
print(person(/* $firstName = */ 'Bertrand', /* $lastName = */ 'Russel')); 

[OK]を、これはperson($lastName='Lennon')限り短くし、エレガントではありませんが、あなたがPHPでそれを持つことはできませんようです。それはスーパーメタプログラミングのトリックなどでコード化するのが最もセクシーな方法ではありませんが、メンテナンスプロセスでどのような解決策を見つけるのが好きですか?

関連する問題