在PHP中这样命名参数是个坏主意吗?


Is it a bad idea to name parameters like this in PHP?

我最近一直在做很多Objective-C编程,现在我要回到PHP,我必须诚实地说,我想念命名参数(一开始我讨厌它们,现在我喜欢它们,想想看)。

无论如何,在PHP中,我有时看到人们将数组传递给函数作为一种命名参数的伪方法(额外的好处是不必担心顺序),但有时这会使函数编写过于复杂。此外,有时我想用命名参数调用函数,但有时不这样做更容易更快。

有人这样做吗?

function calculateArea( $width, $height ) {
    // do calculations here...
}
// and then call the function like so:
calculateArea( $width = 10, $height = 5 );

它似乎工作得很好,至少在我的PHP版本中,我想知道其他人是否也使用这种技术作为命名参数的解决方案。我也想知道是否有人知道一些令人信服的理由,为什么我不应该这样做。

谢谢!

更新:

感谢大家的快速回复。为了让事情更清楚,我只想说,我理解传递关联数组在大多数情况下是一个更好的选择,但有时你正在使用你已经写好的函数,你不想改变它们在你代码的每一部分中的调用方式。另外,有时候你正在使用一个辅助框架,你无法控制函数是如何编写的。

如果我看我一年前写的代码,我看到:echo $zc->expand('Foo', 'Bar', 10, 1, 0, null, null, array('class'=>'code'), false);,这不是很有帮助。

所以,换句话说,我的问题基本上是这样的:
有时通过赋值传递参数给函数更容易阅读。这样做的缺点是什么?它是否适用于所有版本的PHP?

我认为这是一个坏主意,从你没有任何安全的角度来看,如果你得到错误的顺序。使用地图是一种更安全的模拟方式。在局部作用域中设置这些变量的值也会产生副作用,这可能是个问题,也可能不是。

calculateArea( $height = 5, $width = 10 ); # oops!
function calculateArea( $width, $height ) {
    // do calculations here...
}

对于数组(map),它们的顺序是无关紧要的。

calculateArea( array( 'height' => 5, 'width' => 10 ) ) # yea!
function calculateArea( $dimensions ) {
    $width = $dimensions['width'];
    $height = $dimensions['height'];
}

使用calculateArea( $width = 10, $height = 5 )时,您不需要像在Python等其他语言中那样通过名称指定参数。

函数调用中的$width = 10$height = 5只是两个变量赋值表达式。

这仍然像预期的那样工作的原因是赋值表达式不仅赋值,而且还返回赋值:

赋值表达式的值就是赋值。即"$a = 3"的值为3。

因此,有效地calculateArea( $width = 10, $height = 5 )调用calculateArea的参数与calculateArea(10, 5)相同,但它也分配了两个变量:

calculateArea( $width = 10, $height = 5 );
var_dump($width);   // int(10)
var_dump($height);  // int(5)

不应该在函数调用中使用变量赋值,因为这可能会导致意想不到的结果。calculateArea($a = 10, $b = 5)也可以。函数调用完成后,$a === 10, $b === 5。如果这些变量在函数调用之前有不同的值,这些值将被覆盖。

你可以用以下任何一种方式调用你的函数:

calculateArea (10, 5);

或:

calculateArea(宽度、高度美元);

或:

calculateArea (xvar美元,5);

但是在函数调用中赋值通常是不好的做法。这在技术上是正确的,但使代码难以阅读。而不是这样做:

计算区域($width = 10, $height = 5);

这样做:

$width = 10;
$height = 5;
calculateArea( $width, $height );

或:

$width = 10;
$height = 5;
calculateArea( 10, 5 );

它们都具有相同的效果,但是在函数外声明变量可以明确它们的作用域。

现在您知道了,PHP没有这个特性。但我想说,传递数组也是一种不好的方式。在这种情况下,你必须在内存中保存(或者在phddoc注释中最好的情况下),哪些键可以在数组中使用,你不能设置'默认值',你可以很容易地在数组的键名中输入错误。
所以我更喜欢在这种情况下使用对象(因为PHP也没有"结构")。在object中,您可以设置默认值,您可以在函数声明中设置所需对象的类型,并且在IDE中,您可以获得对象字段名称的代码完整。为例:

class DimensionsParams
{
    public $width = 5;
    public $height;
}
function calculateArea(DimensionsParams $params)
{
    // do calculations here...
    return $params->height*$params->width;
}

当然,它不是每个函数的最佳选择,但它是"命名参数"的最佳变体(在我看来)。