偶尔我会编写一个带有单个输入的PHP函数,一个包含所有函数输入的关联数组。这样做的好处就是不必记住正确的输入顺序,但我也注意到它使得对大型代码库的实现更容易实现;当我需要添加另一个变量,并且该变量必须通过4或5个预先存在的函数时,当我可以将它粘在数组中并将其传递时,它会更容易。
我的问题是,这样做有不利之处吗?
我很少看到以这种方式在示例中编写的函数,或者我使用的开源函数,这让我相信可能存在缺点。如果不是不这样做的理由那么为什么不这样写所有函数呢?
更新
感谢您的所有答案。看起来两个主要问题突出:
代码可读性 - 无法分辨哪些变量进入函数以及它们的用途
变量蠕变 - 可能会结束从一个函数到下一个函数的大量数组;一个人不应该将参数传递给不需要它们的函数
这两点都是我没想过的好点。
似乎一般的要点是,这是一个问题的代码,应该转换为类。不幸的是,在这个特定的项目中,这样的重构超出了范围,但我也认为Bill Karwin的解决方案很好 - 传递一组可选变量
答案 0 :(得分:12)
为什么不以这种方式编写所有函数?
就此而言,为什么不完全忘记参数,并使用全局变量? (开玩笑)
传递关联数组有一个有用的优点:可以使多个函数参数可选,并且可以传递 N 参数的值,而不必传递* N-1的值*参数。
但是如果你没有传递它们,你就无法使用编译时错误来制作强制参数。你也不能宣布类型检查。
您必须在被调用函数内编写代码以检查所需参数的存在和类型。
我使用的替代方法是为必需的参数声明常规参数,然后作为最后一个(可选)参数,声明一个名为$options
的关联数组,其中只包含可选项。
function database_connect($dbname, $user, $password, array $options = array())
答案 1 :(得分:9)
缺点是,任何查看代码的人(除了你)都不知道哪些参数会进入某个方法,它们来自何处,或者它们的用途。他们也不知道如何调用一个方法,因为如果不仔细查看代码在“参数数组”中需要的内容就不清楚了。
答案 2 :(得分:2)
大概有一个缺点就是你最终会得到太多的参数。 这导致了代码可能失去可读性的问题。
在严格的面向对象的方法中,您将所有这些“通过”多个函数调用的参数转换为包含这些方法的类的实例变量。
你永远不应该将参数传递给它们实际上不需要的函数。
答案 3 :(得分:2)
这不一定是一个想法,因为PHP缺少许多其他现代编程语言(Python,Ruby等)中的“关键字参数”功能。但是,肯定存在一些问题:
如果您更改了某个函数接受的参数,那么您可能必须更改一些代码,以便匹配新参数。
如果您正在广泛使用这些数组,并且在许多函数调用中使用数组并简单地“传递它”,这可能表明您应该考虑将其中一些参数转换为结构化类
如果您将这些数组用作可变数据结构,则不一定知道调用该函数后所拥有的数组与传入的数组相同。这可能会回到在某些时候得到你。
答案 4 :(得分:1)
列出每个参数可以提高代码的可读性。传递单个关联数组不一定能解释传递给函数的数据类型。
答案 5 :(得分:1)
如果我拿起你的函数并看到它只是在单个函数参数中开始引用哈希值,我会有点困惑。使用@param明确说明变量并在docblock中提供一些文档有很大帮助。与可读性列表参数的产生相比,必须在两个地方添加一个参数是一个较小的成本。
答案 6 :(得分:1)
我个人使用以下方法:
在函数定义中将参数声明为数组;
建立“默认值”关联。阵列;
匹配将带有默认值的params传递给我在函数内部使用的权威参数assoc.array。为此,我使用param_default()函数。
通过遵循此方法,我避免了强制性的params问题并管理默认值;以任何顺序传递密钥的能力都非常舒适。
// default values fx.
function param_default( $def = array(), $parameters= array() ){
$parm_diff = array();
$ak=array();
$va=array();
$parm = array();
foreach($def as $key=>$values) if(!in_array($key, array_keys($parameters))){
$ak[]=$key;
$va[]=$values;
}
$parm_diff = array_combine($ak,$va);
$parm = array_merge($parm_diff,$parameters);
unset($parm_diff, $ak,$va);
return $parm;
}
所以这是一个简单的用法示例:
<?php
// sample use
function my_func( $parameters = array() ){
$def = array(
'first' => 1,
'second' => 'foo',
'third' => -1
);
$parm = param_default( $def, $parameters );
//hereon I can use my array
var_dump($param);
if ($param['second'] !=='foo'){
echo 'Not foo!!';
// whatever...
}
return true;
}
?>
输出示例:
// calling my_fun()
$example = my_func( array('second'=>'bar') );
// results in
$param array:
'first' => 1,
'second' => 'bar',
'third' => -1
答案 7 :(得分:0)
这里最大的代码味道是添加另一个变量会级联4-5个不同的函数。我无法想到这需要发生的原因。
听起来你需要将这个代码重构为一个类,这样你就可以将值传递给构造函数一次,并将它们保存为成员变量。
答案 8 :(得分:0)
如果您具有单独命名和传递的参数,则可以更轻松地生成文档。您可能认为使用数组可以更容易地添加新代码,但其优势并未超出可读性。再离开你的代码2个月然后回来......弄清楚以什么顺序将params添加到你的阵列中,哪些情况会成为一个大问题。
答案 9 :(得分:0)
在某些情况下,我觉得这很有意义,但通常你可以通过创建行为略有不同的多种方法来简化事情。然后,该方法的名称将明确它的用途。
一般情况下,如果您的功能有&gt; 3个论点无论如何都会变得难以理解。
作为替代方案,经常使用的模式是将函数的单个参数作为(分类)对象。 '参数类'将准确定义支持的内容。
答案 10 :(得分:0)
如果某人仍在寻找解决方案 - 这里是(示例函数是__ construct()):
答案 11 :(得分:0)
如果您的问题是如何将数组作为函数的输入,这是您的答案:
<?php
function city($input){
$i=count($input['iran']);
$result="";
for($b=1;$b<=$i;$b++){
$result.='<div style="background:gold">'.$input['iran'][$b].'</div>';
}
return $result;
}
$cityName['iran'][1]="Tehran";
$cityName['iran'][2]="Qom";
$cityName['iran'][3]="MashHad";
$cityName['iran'][4]="Isfahan";
$cityName['iran'][5]="Shiraz";
$cityName['iran'][6]="Yazd";
echo city($cityName);
?>
答案 12 :(得分:0)
创建功能:
function testing($argumentos) {
$var_1 = $argumentos['var_01'];
$var_2 = $argumentos['var_02'];
echo $var_1 . " " . $var_2;
}
调用该函数:
testing(array('var_01' => "mierda", 'var_02' => "conio!"));
输出:
mierda conio!