我喜欢使用key =>值对(数组)作为参数而不是单个参数来创建我的PHP函数。
例如,我更喜欢:
function useless_func($params) {
if (!isset($params['text'])) { $params['text'] = "default text"; }
if (!isset($params['text2'])) { $params['text2'] = "default text2"; }
if (!isset($params['text3'])) { $params['text3'] = "default text3"; }
echo $params['text'].$params['text2'].$params['text3'];
return;
}
我不喜欢:
function useless_func($text = "default text", $text2 = "default text2", $text3 = "default text3") {
echo $text.$text2.$text3;
return;
}
我第一次在Wordpress代码库中看到过以这种方式完成的事情。
我更喜欢数组的原因:
我正在与同事讨论这个问题,他说它没用,只会导致额外的代码,而且设置默认值要困难得多。基本上,他完全不同意我的所有三点。
我正在寻找可能提供见解的专家的一般建议和指导:有什么更好或更恰当的方法来做到这一点?
答案 0 :(得分:15)
嗯,这有点有用。但是对于一些经常传递的论据,最好使用像function some($a1, $a2)
这样的经典传递。我在我的代码中这样做:
function getSome(SomeClass $object, array $options = array())
{
// $object is required to be an instance of SomeClass, and there's no need to get element by key, then check if it's an object and it's an instance of SomeClass
// Set defaults for all passed options
$options = array_merge(array(
'property1' => 'default1',
'property2' => 'default2',
... => ...
), $options);
}
所以,你可以看到我也喜欢那种代码风格,但是对于核心参数我更喜欢经典风格,因为如果我使用你的代码风格,那么PHP会控制我应该做的更多事情。
答案 1 :(得分:13)
在大多数情况下,将所有数据传递到数组中是个坏主意。
在功能中它似乎与injecting相反。
可以按任何顺序提供函数参数
我没有这样的偏好。我不明白这种需要。
更容易阅读代码/更多自我记录(在我看来)
大多数IDE会向您展示函数需要的不同参数。如果有人看到像foo(Someclass $class, array $params, $id)
这样的函数声明,那么函数需要的是什么。我不同意单个参数参数更容易阅读或自我记录。
不容易出错,因为在调用函数时我必须调查正确的数组键
允许人们在不知道值将被默认的情况下传入数组并不接近“不容易出错”。让人们在使用它之前必须阅读你的功能是一种永远不会被使用的可靠方法。声明它需要三个参数及其默认值是 less 容易出错,因为调用你的函数的人会知道参数将被默认为哪些值,并相信它会呈现他们期望的结果。
如果您要解决的问题是参数太多,那么正确的决定是将您的函数重构为较小的函数,而不是隐藏数组后面的函数依赖。
答案 2 :(得分:9)
我假设您正在询问是否一件好事来编写所有函数,以便它们只接受一个参数,并且该参数是一个数组?
如果您是唯一一个曾经打算使用代码的人,那么您可以做自己喜欢的事情。但是,通过将所有参数值传递给数组,其他任何人都必须更加努力地了解函数的作用以及它们为何/如何使用它,特别是如果它们使用具有自动完成功能名称的IDE他们并没有把它称为“功能签名”。
我建议数组参数保留用于您不知道将有多少项(例如一系列数据项)的项目,或者用于相关选项/设置组(可能是正在进行的操作)在你提到的Wordpress示例中?)。
如果你继续对数组参数进行全面的处理,那么你至少应该意识到它对可读性的影响,并采取一些措施来解决这个问题。
答案 3 :(得分:5)
你的同事是对的。它不仅是相同功能的更多代码,更难以阅读并且可能降低了性能(因为您需要为每个参数调用isset
并且您需要访问数组来设置值)。
答案 4 :(得分:4)
这与Cargo Cult programming接壤。你说这更具可读性和自我记录性。我会问怎么样?要知道如何使用您的函数/方法,我必须阅读代码本身。我无法从签名本身知道如何使用它。如果您使用支持方法签名提示的任何半正式IDE或编辑器,这将是一个真正的PITA。另外,您将无法使用PHP的类型提示语法。
如果您发现编码了大量参数,尤其是可选参数,则表明您的设计可能存在问题。考虑一下你可能会怎么做。如果某些或所有参数都是相关的,那么它们可能属于他们自己的类。
答案 5 :(得分:4)
使用array_merge()
可以正常工作,但也可以使用+
运算符;它以另一种方式工作,它只添加一个尚未给出的默认值。
function useless_func(array $params = array())
{
$params += array(
'text' => 'default text',
'text2' => 'default text2',
'text3' => 'default text3',
);
}
另请参阅:Function Passing array to defined key
使用数组作为函数参数时,您无法获得的一些事情是:
答案 6 :(得分:0)
你的同事很疯狂。传递数组作为函数参数是完全可以接受的。它在包括Symfony和Doctrine在内的许多开源应用程序中很流行。我总是遵循2参数规则,如果一个函数需要两个以上的参数,或者你认为将来会使用两个以上的参数,请使用数组。 IMO允许最大的灵活性并减少在参数传递不正确时可能出现的任何调用代码缺陷。
确实需要更多的工作来从数组中推断出值,并且你必须考虑所需的元素,但它确实使得添加功能变得更加容易,并且远比将13个参数传递给函数要好得多。它需要被召唤的时间。
以下是一段显示所需与可选参数的代码,只是为了给您一个想法:
// Class will tokenize a string based on params
public static function tokenize(array $params)
{
// Validate required elements
if (!array_key_exists('value', $params)) {
throw new Exception(sprintf('Invalid $value: %s', serialize($params)));
}
// Localize optional elements
$value = $params['value'];
$separator = (array_key_exists('separator', $params)) ? $params['separator'] : '-';
$urlEncode = (array_key_exists('urlEncode', $params)) ? $params['urlEncode'] : false;
$allowedChars = (array_key_exists('allowedChars', $params)) ? $params['allowedChars'] : array();
$charsToRemove = (array_key_exists('charsToRemove', $params)) ? $params['charsToRemove'] : array();
....
答案 7 :(得分:0)
@Mike,您还可以将$ params参数“解压缩”到局部变量中,如下所示:
// Class will tokenize a string based on params
public static function tokenize(array $params)
{
extract($params);
// Validate required elements
if (!isset($value)) {
throw new Exception(sprintf('Invalid $value: %s', serialize($params)));
}
// Localize optional elements
$value = isset($value) ? $value : '';
$separator = isset($separator) ? $separator] : '-';
$urlEncode = isset($urlEncode) ? $urlEncode : false;
$allowedChars = isset($allowedChars) ? $allowedChars : array();
$charsToRemove = isset($charsToRemove) ? $charsToRemove : array();
...
相同的实施,但更短。
答案 8 :(得分:0)
我已经在很多场合使用数组代替了很长的参数列表并且运行良好。我同意这篇文章中那些提到代码编辑无法提供参数提示的人。问题是,如果我有10个参数,并且前9个为空/空,则在调用该函数时它变得难以处理。
我也有兴趣听听如何重新设计一个需要大量参数的函数。例如,当我们有一个函数根据设置的某些参数构建SQL语句时:
function ($a1, $a2, ... $a10){
if($a1 == "Y"){$clause_1 = " something = ".$a1." AND ";}
...
if($a10 == "Y"){$clause_10 = " something_else = ".$a10." AND ";}
$sql = "
SELECT * FROM some_table
WHERE
".$clause_1."
....
".$clause_10."
some_column = 'N'
";
return $sql;
}
我希望看到PHP能够添加一个本机帮助函数,该函数可以在被调用的函数中使用,这将通过进行必要的类型检查来帮助传递参数数组。 PHP在某种程度上通过创建func_get_args()函数来识别这一点,该函数允许以任何顺序传递参数。但这只会传递值的COPY,所以如果你想将对象传递给函数,这将是一个问题。如果存在这样的功能,那么代码编辑就能够选择它并提供有关可能参数的详细信息。