20

このような関数を書くと、名前付き関数パラメータを PHP でエミュレートできます。

function pythonic(array $kwargs)
{
    extract($kwargs);
    // .. rest of the function body
}

// if params are optional or default values are required
function pythonic(array $kwargs = array('name'=>'Jon skeet'))
{
    extract($kwargs);
    // .. rest of the function body
}

IDE でインテリセンスを失うこと以外に、このアプローチの他の考えられる欠点は何ですか?

編集:

セキュリティ:この場合、抽出された変数は関数スコープに限定されているため、セキュリティは問題ではありませんか?

4

5 に答える 5

35

連想配列を使用して名前付きパラメーターを渡すことをお勧めしますが、それらを抽出せずに配列に保持します。

function myFunc(array $args) {
    echo "Hi, " . $args['name'];
    // etc
}

これにはいくつかの理由があります。この関数を見ると、関数に渡された引数の 1 つを参照していることがわかります。それらを抽出しても、extract()あなた (または次の人) は、この " $name" 変数がどこから来たのか疑問に思って頭をかきむしっていることに気付かないでしょう。引数をローカル変数に抽出していることわかっていても、ある程度は推測ゲームです。

次に、他のコードが引数を上書きしないようにします。$fooおよびという名前の引数のみを期待して関数を作成した可能性がある$barため、他のコードでは$baz = 8;、たとえば を定義します。後で、関数を拡張して "baz" という新しいパラメーターを取りたいと思うかもしれませんが、他の変数を変更するのを忘れてしまうと、引数に何が渡されても、$baz常に 8 に設定されます。

配列を使用することにもいくつかの利点があります (これらは、配列を抽出または残す方法に等しく適用されます): と呼ばれる各関数の先頭に変数を設定できます$defaults

function myFunc (array $args) {
    $default = array(
        "name" => "John Doe",
        "age" => "30"
    );
    // overwrite all the defaults with the arguments
    $args = array_merge($defaults, $args);
    // you *could* extract($args) here if you want

    echo "Name: " . $args['name'] . ", Age: " . $args['age'];
}

myFunc(array("age" => 25)); // "Name: John Doe, Age: 25"

$args対応する値がないすべてのアイテムを削除することもでき$defaultます。このようにして、どの変数があるかを正確に知ることができます。

于 2009-03-25T07:21:12.230 に答える
8

これを行う別の方法があります。

/**
 * Constructor.
 * 
 * @named string 'algorithm'
 * @named string 'mode'
 * @named string 'key'
 */
public function __construct(array $parameter = array())
{
    $algorithm = 'tripledes';
    $mode = 'ecb';
    $key = null;
    extract($parameter, EXTR_IF_EXISTS);
    //...
}

この設定により、デフォルトのパラメーターを取得し、IDEのインテリセンスを失うことはなく、EXTR_IF_EXISTSは、変数として既に存在する配列キーを抽出するだけで安全になります。

(ちなみに、提供した例からデフォルト値を作成することは適切ではありません。これは、paramの配列が「name」インデックスなしで提供された場合、デフォルト値が失われるためです。)

于 2009-03-25T11:29:51.853 に答える
6

私の経験では、このアプローチが本当に有益なのは、次の 2 つのいずれかが当てはまる場合のみです。

  1. 酌量すべき理由が何であれ、あなたの主張の署名は大きいです。私は最大値として 6 を使用しています。特定の理由があるわけではありませんが、正しいように見えますが、この数値が恣意的であることは認めます。
  2. 引数のすべてまたは多くはオプションであり、5 番目の引数などの値を設定するだけでよい場合もあります。書くの面倒くさいsomeFunc( null, null, null, null, 1 );

これらのいずれかに該当する場合、名前付きパラメーターを連想配列で偽造することが適切な実装である可能性があります。いつ抽出を避けるべきか (または完全に避けるべきか) を知る以外に、他の欠点をすぐに思いつくことはできません。

そうは言っても、多くの場合、これらの問題は両方ともリファクタリングによって解決できます。

于 2009-03-25T06:02:17.803 に答える
2

私の経験では、この方法の欠点は、記述するコードが増えることです。次のようなものを検討してください。

function someFunc($requiredArg, $arg1 = "default11", $arg2 = "default2") {

配列内のすべてを渡すときにこの動作をシミュレートするには、より多くのコードを記述する必要があり、「関数シグネチャ」は「明確で明白」ではなくなります。

function someFunc($requiredArg, $optionalArgs) {
    // see other answers for good ways to simulate "named parameters" here

PHPが将来のリリースでそれに対処するのは良い考えではないかと思っています.PascalやVB構文のようなものを関数の引数に利用できるようにするかもしれません.

とにかく、本当に必要な場合にのみ単一の配列でパラメーターを渡します。たとえば、開発中に大幅に変更される可能性のあるパラメーター セットを持つ関数などです。これらの関数には通常、多数のパラメータもあります。

于 2011-11-04T16:47:05.207 に答える