Передача массива для установки переменной

Я часто вижу эту идиому, читая php код:

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

Здесь я - беспокойство со способом, которым используется параметр. Если бы я был в шепелявости, то я сделал бы:

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

Но так как я нахожусь в PHP, у меня был бы конструктор, которые берут список параметра и позволяют им быть пустыми, если там не требуют.

Таким образом, что делает Вас, парни думают о наличии массива как параметр в другом делать некоторый initialization-whatever?

В другом для ответа необходимо взять в учетной записи точку зрения пользователя функции и разработчика API.

1
задан Bhargav Rao 30 April 2019 в 07:04
поделиться

3 ответа

Лично мне не нравится эта идиома. Вместо этого я предпочитаю иметь длинный список параметров, если это необходимо.

Проблема в том, что я не могу узнать элементы, которые массив не может принять, глядя на сигнатуру функции. Вдобавок к этому, реализации почти никогда не проверяют, есть ли какой-либо ключ, который не распознан, поэтому, если я неправильно введу ключ массива, я не получу предупреждения.

Лучшей альтернативой была бы передача объекта конфигурации. По крайней мере, там IDE может предоставить мне подсказки по доступным объектам конфигурации, а вычисленные значения по умолчанию для отсутствующих параметров могут быть перемещены из конструктора, который вы показываете геттерам в объекте конфигурации. Очевидная альтернатива - предоставить установщики для нескольких опций конфигурации; хотя это не помогает для требуемых для каждого, не может быть предоставлено значение по умолчанию.

1
ответ дан 3 September 2019 в 00:00
поделиться

Мне очень нравится шаблон проектирования «массивов опций». Если бы 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
        }
    }
}

Одна вещь. Если вы это сделаете, ПОЖАЛУЙСТА, задокументируйте требуемые параметры. Это значительно облегчит жизнь тем, кто последует за вами.

1
ответ дан 3 September 2019 в 00:00
поделиться

Я нахожу использование массивов в качестве параметров полезным, когда есть много необязательных параметров. Обычно я использую array_merge, чтобы объединить переданный массив с массивом "defaults". Проверка не требуется. Если у вас есть обязательные параметры, вы можете использовать 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);
}
0
ответ дан 3 September 2019 в 00:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: