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を使用しているので、パラメーターのリストを取得し、必要がない場合はそれらをnullにするコンストラクターが必要です。

では、初期化などを行うために、他のパラメーターとして配列を使用することについてどう思いますか?

他に答えるには、関数のユーザーとAPIの設計者の視点を考慮に入れる必要があります。

4

3 に答える 3

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 に答える
1

個人的には、そのイディオムは嫌いです。必要に応じて、代わりに長いパラメーター リストを使用することを好みます。

問題は、関数のシグネチャを見て、配列が取り込めない要素を知ることができないことです。その上、認識されないキーがあるかどうかを実装がチェックすることはほとんどないため、配列キーのスペルを間違えても警告は表示されません。

より良い代替手段は、構成オブジェクトを渡すことです。少なくとも、IDE は使用可能な構成オブジェクトに関するヒントを提供し、欠落しているオプションの計算された既定値は、構成オブジェクトのゲッターに表示するコンストラクターから移動できます。明らかな代替手段は、いくつかの構成オプションのセッターを提供することです。これは、それぞれに必要なものには役に立ちませんが、デフォルトを提供することはできません。

于 2010-06-07T15:21:48.490 に答える
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 に答える