将数组传递给PHP函数

4
我看到一些人提出了类似的问题,但我需要对这个特定主题有更多澄清。
我的几个函数需要传递多个参数,甚至有一些函数需要10个参数。(最初没有计划,只是随着时间的推移增加了)
查找第7个参数并没有问题,但这很繁琐。大多数时候我知道应该传递哪些参数,只是不知道它们的位置。
我有一些想法来简化这个过程。
a)只传递一个参数,但用某些分隔符分割所有参数。(但那是个坏主意!因为我仍然需要记住每个参数的位置。)
function myfunc('data|data|data|'){
          // explode the string
}
b) 传递一个包含键和值的数组,查找函数内部的键名,并相应地执行操作。
function myfunc(array('arg1' => 'blah blah', 'arg2' => 'more blah')){
  // loop through the array
}

c) 保持原样。

function myfunc($arg1,$arg2,$arg3,$arg4,$arg5........){
// yay

}

因此,我正在寻求其他选项和更好的想法来处理有着不断增长参数列表的函数。


3
这些函数是什么,这些参数是什么?很可能是设计不良的后果,参数数量可以大幅减少。 - Your Common Sense
虽然在当前版本中,这个问题是毫无意义和主观的。 - Your Common Sense
1
为什么不重构你的代码并将函数拆分成几个小函数?为什么不使用对象并将它们传递给其他对象?大约有10个参数应该引起糟糕设计的警示。 - kgilden
8个回答

8
在我看来,最好的方法是通过传递一个关联数组来实现。这样你可以立即看到每个参数的作用。只需确保使用描述性的名称,而不是arg1和arg2。
另一个关联数组的优点是,您不必关心参数传递的顺序。
只需记住,如果您使用关联数组,则会失去PHP分配默认值的原生方式,例如:
function doSomething($arg1 = TRUE, $arg2 = 55) { }

所以,您需要做的是创建自己的默认选项集,然后合并您的数组:
function doSomething( $props = array() )
{
    $props = array_merge(array(
        'arg1' => TRUE,
        'arg2' => 55
    ), $props);

    // Now use the $props array
}

在foreach的头部应该是$props而不是$options。 - klaustopher
+1 表示通过使用关联数组;-1 表示试图重复造轮子 - zzzzBov
@zzzzBov - 在大多数情况下,您不需要使用array_merge_recursive。然而,array_merge可以解决问题(+=也可以),我已经更新了我的答案。 - Joseph Silber
@Joseph Silber,你能举个例子说明何时不想使用array_merge_recursive吗? - zzzzBov
@zzzzBov - 也许我漏掉了什么,但我认为array_merge_recursive是没有意义的。看看我的array_merge_recursivearray_merge的例子,然后告诉我哪一个更有意义。 - Joseph Silber
@JosephSilber,通常我使用多级关联数组(带有子选项的选项)。不过,我能理解您使用标准列表数组的观点。我认为这确实归结于使用适合工作的正确工具。 - zzzzBov

2

当你有许多可混合和匹配的可选参数时,请使用myfunc($options)形式。使用array_merge_recursive与默认选项数组,你将会得到更好的结果。


2
b)(关联数组)是最简单、最适应性强的(因为它允许模拟默认的关键字参数),并且最不容易出错的变体。

真的,它似乎是最适应性强的,我可以清楚地看到我的关键词是什么,减少了猜测。我将其测试过,到目前为止它对我来说一直表现良好。 - coffeemonitor

1

首先,看看你是否可以引入参数对象。不一定要替换所有7个参数,但也许可以减少它们的数量。

接下来,检查函数本身——为什么它需要这么多参数,也许它做了太多的事情?用方法替换参数/用显式方法替换参数是否适用?

顺便说一句,重构是很好的阅读材料!


0

关联数组,以参数名称为键,顺序不重要(不要忘记记录预期的键):

function myFunc(array $args)
{
    # default values
    $args += array('arg1' => 'default1', 'arg2' => 'default2');
}

有时候,您希望验证从输入中删除了所有不重要的键。这种情况下,一个有用的函数是array_intersect_key文档

0
function myfunc($arg1,$arg2,$arg3,$arg4,$arg5........){ 根据提供的有限信息,我必须说保持原样。原因是您的函数签名显示没有任何参数具有默认值(它们都是必需的)。 如果将其变为关联数组,则会删除解析器警告不良调用函数的能力,即:
Missing argument 2 for some_function, called in [etc.]

如果你记不住所有的参数,IDE可以帮助你提供函数调用的辅助。

基本上,如果它是必需的参数,它应该在函数签名中。


0
根据函数的意图,有时传递对象是合适的。

0

我们不谈论解决方案#1。你已经说过它很糟糕了...

我喜欢第二个想法,即传递这个哈希/关联数组。感觉很像Ruby :) 你正在做的事情是放弃一些免费获得的检查。如果调用一个函数并忘记一个参数,运行时会抱怨并停止执行脚本。 在您的场景中,您必须在函数内执行所有这些检查:是否提供了所有必要的选项?值是否为正确的类型等等?

我会说,如果只有你自己在编写代码,那么决定就取决于你的口味。 如果有其他人与您合作,请问他们的意见。在那之前,我会坚持使用具有7个参数的经典方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接