在PHP中模拟命名函数参数,好主意还是坏主意?

2022-08-30 20:27:10

命名函数参数可以在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中失去智能感之外,这种方法还有其他可能的缺点吗?

编辑:

安全:在这种情况下,安全性难道不应该是一个问题,因为提取的变量仅限于函数范围吗?


答案 1

我建议使用关联数组来传递命名参数,但将它们保留在数组中而不提取它们。

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

这有几个原因。查看该函数,您可以非常清楚地看到我指的是传递到函数中的一个参数。如果你提取它们,并且没有注意到你(或下一个人)会在那里挠挠头,想知道这个“”变量来自哪里。即使你知道你正在提取局部变量的参数,在某种程度上,它仍然是一个猜谜游戏。extract()$name

其次,它确保其他代码不会覆盖参数。您可能已经编写了函数,只期望参数名为 和 ,因此在其他代码中,例如,您定义了 。稍后,您可能希望扩展函数以采用名为“baz”的新参数,但忘记更改其他变量,因此无论在参数中传递什么,都将始终设置为8。$foo$bar$baz = 8;$baz

使用数组也有一些好处(这些好处同样适用于提取或离开数组的方法):您可以在每个函数的顶部设置一个名为:$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


答案 2

这是您可以执行此操作的另一种方法。

/**
 * 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通过提取已作为变量存在的数组密钥来使其安全。

(顺便说一句,从您提供的示例中创建默认值并不好,因为如果提供的参数数组没有“name”索引,则默认值将丢失。


推荐