1

我在阅读php代码时经常看到这个成语:

public function __construct($config)
{
    if (array_key_exists('options', $config)) {
       ...
    }
    if (array_key_exists('driver_options', $config)) {
        ...
    }
}

这里我关心的是参数的使用方式。如果我在 lisp 中,我会这样做:

(defun ct (&key options driver_options) 
       (do-something-with-option-and-driver_option))

但是由于我在 PHP 中,我宁愿有一个构造函数来获取参数列表,如果不需要,则让它们为空。

那么你们如何看待将数组作为参数在其他中进行一些初始化或其他操作?

在其他回答中,您必须考虑函数用户和 API 设计者的观点。

4

3 回答 3

1

就个人而言,我不喜欢这个成语。如有必要,我更喜欢有一个长参数列表。

问题是我无法通过查看函数签名来知道数组无法获取的元素。最重要的是,实现几乎从不检查是否有任何无法识别的键,所以如果我拼错了数组键,我不会收到任何警告。

一个更好的选择是传递一个配置对象。至少,IDE 可以为我提供有关可用配置对象的提示,并且可以将计算出的缺失选项的默认值从您显示的构造函数移到配置对象中的 getter。显而易见的替代方法是为几个配置选项提供设置器;尽管这对每个所需的都没有帮助,但无法提供默认值。

于 2010-06-07T15:21:48.490 回答
1

我非常喜欢“选项数组”的设计模式。如果 PHP 支持 Python 的参数扩展,那么我会同意使用长参数列表。但我只是发现foo(1, 2, 'something', true, 23, array(4), $bar);它真的不可读。当需要设置超过 3 或 4 个参数时,我通常会使用数组...

我建议“清理”构造函数是创建一个受保护的方法来访问配置变量(最好在基类中):

abstract class Configurable {
    protected $options = array();
    protected $requiredOptions = array();

    public function __construct(array $options = array()) {
        $this->options = $options;
        foreach ($this->requiredOptions as $option) {
            if (!isset($this->options[$option])) {
                throw new InvalidArgumentException('Required argument [$'.$option.'] was not set');
            }
        }
    }

    protected function _getOption($key, $default = null) {
        return isset($this->options[$key]) ? $this->options[$key] : $default;
    }
}

然后,在你的类中,你可以重载 requireOptions 数组来定义需要设置的东西

class Foo extends Configurable {
    protected $requiredOptions = array(
        'db',
        'foo',
    );

    public function __construct(array $options = array()) {
        parent::__construct($options);
        if ($this->_getOption('bar', false)) {
            //Do Something
        }
    }
}

一件事。 如果您这样做,请记录所需的选项。对于那些跟随你的人来说,这将使生活变得更加轻松。

于 2010-06-07T15:37:09.497 回答
0

当有很多可选参数时,我发现使用数组作为参数会很有帮助。通常我会使用 array_merge 将传递的数组与“默认”数组合并。无需检查。如果您有必需的参数,您可以使用 array_diff_key 来确定是否缺少任何必需的参数。

function params($p_array) {
    static $default_vals = array('p1'=>1, 'p2'=>null, 'p3'=>'xyz');
    static $rqd_params = array('p1'=>null, 'p3'=>null);
    // check for missing required params
    $missing_params = array_diff_key($rqd_params, $p_array);
    if ( count($missing_params)>0 ) {
       //return an error (i.e. missing fields)
       return array_keys($missing_params);
    }
    // Merge passed params and override defaults
    $p_array = array_merge($default_vals, $p_array);
}
于 2010-06-07T15:58:40.210 回答