PHP函数参数-是否使用数组?

PHP函数参数-是否使用数组?,php,arrays,function,arguments,Php,Arrays,Function,Arguments,我喜欢使用key=>value对(数组)作为参数而不是单个参数来创建PHP函数 例如,我更喜欢: function useless_func($params) { if (!isset($params['text'])) { $params['text'] = "default text"; } if (!isset($params['text2'])) { $params['text2'] = "default text2"; } if (!isset(

我喜欢使用key=>value对(数组)作为参数而不是单个参数来创建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代码库中广泛地看到这样做的情况

我喜欢阵列的原因是:

  • 函数参数可以按任何顺序提供
  • 更容易阅读代码/更多的自我记录(在我看来)
  • 不太容易出错,因为在调用函数时,我必须研究正确的数组键
我和一位同事讨论过这个问题,他说这没用,只会导致额外的代码,而且设置默认值要困难得多。基本上,他在这三点上完全不同意我的观点


我想从专家那里得到一些一般性的建议和指导,他们可能会提供一些见解:做这件事的更好或更合适的方法是什么?

嗯,这是很有用的。但是对于一些总是传递的参数,最好使用经典的传递,比如
函数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); 
}

所以,正如你所看到的,我也喜欢这种代码风格,但对于核心参数,我更喜欢经典风格,因为如果我使用you代码风格,PHP可以控制更多我应该做的事情。

你的同事太疯狂了。将数组作为函数参数传入是完全可以接受的。它在许多开源应用程序中非常流行,包括Symfony和doctor。我一直遵循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();

....

你的同事是对的。它不仅为相同的功能提供了更多的代码,而且更难读取,并且可能降低了性能(因为您需要为每个参数调用
isset
,并且需要访问数组来设置值).

我想你会问,写所有的函数,使它们只接受一个参数,并使该参数成为一个数组,这是否是一件好事

如果你是唯一一个会处理你的代码的人,那么你可以做你喜欢的事情。但是,通过将所有参数值传递给数组,其他任何人都必须更加努力地理解函数的功能以及为什么/如何使用它,特别是如果他们使用的IDE具有函数名自动完成等功能。他们不会无缘无故地将其称为“函数签名”

我建议将数组参数保留给您不知道有多少项的项(例如一系列数据项),或者保留给相关选项/设置组(这可能是您提到的Wordpress示例中发生的情况?)

如果您继续对数组参数采用笼统的方法,那么您至少应该意识到它对可读性的影响,并采取一些措施来解决这个问题。

这一点非常重要。你说这更具可读性和自我记录能力。我会问怎么做?要知道如何使用函数/方法,我必须阅读代码本身。我无法从签名本身知道如何使用它。如果您使用任何支持方法签名的半体面IDE或编辑器,这将是一个真正的PITA。另外,您将无法使用PHP的类型暗示语法

如果您发现自己正在编写大量参数,尤其是可选参数,那么这表明您的设计可能有问题。想想你可能会怎么做。如果部分或所有参数相关,则它们可能属于自己的类。

使用
数组_merge()
可以正常工作,但也可以使用
+
操作符;它的工作原理是另一种,它只在尚未给出默认值的地方添加默认值

function useless_func(array $params = array())
{
    $params += array(
        'text' => 'default text',
        'text2' => 'default text2',
        'text3' => 'default text3',
    );
}
另见:

使用数组作为函数参数时,有几件事是无法做到的:

  • 类型检查(仅适用于对象和数组,但在某些情况下可能很有用)
  • 智能(er)文本编辑器具有代码洞察功能,可以显示函数理解的参数;虽然可以在函数docblock中添加可能的键,但使用数组可以去掉该功能
  • 由于#2,它实际上更容易出错,因为您可能会键入错误的数组键
  • @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();
    


    相同的实现,但更短。

    我在许多情况下使用数组替换了一长串参数,效果很好。我同意本文中提到的代码编辑器无法为参数提供提示的观点。问题是,如果我有10个参数,并且前9个参数为空/null,那么调用该函数时就会变得很麻烦

    我还想听听一个关于如何重新设计一个需要很多参数的函数的例子。例如,当我们有一个函数根据设置的某些参数构建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能够添加一个本机helper函数,该函数可以在调用的函数中使用,该函数通过执行必要的类型检查来帮助传递参数数组。PHP通过创建func_get_args()函数在一定程度上认识到了这一点,该函数允许以任何顺序传递参数。但这只会传递一个值的副本,所以如果