Тестирование необязательных аргументов в PHP

У меня есть несколько методов "setter" по классам, и для удобства я добавил необязательный параметр $previous, который принимает аргумент по ссылке и заполняет его существующим значением, прежде чем заменить его новым. Например:

public function set_value($key, $value, &$previous = null)
{
    $previous = $this->get_value($key);
    $this->_values[$key] = $value;
    return $this;
}

Это прекрасно работает; однако в некоторых обстоятельствах соответствующий метод "getter" требует больших затрат времени, и его безусловный запуск является пустой тратой времени. Я решил проверить:

if(null !== $previous)
{
    $previous = $this->get_value($key);
}

Однако это не работает, так как часто переменная, переданная в качестве аргумента для $previous, не была ранее определена в своей области видимости, и по умолчанию все равно принимает значение null. Единственное решение, которое мне удалось найти:

public function set_value($key, $value, &$previous = null)
{
    $args = func_get_args();
    if(isset($args[2])
    {
        $previous = $this->get_value($key);
    }
    $this->_values[$key] = $value;
    return $this;
}

Или, если перефразировать:

if(array_key_exists(2, func_get_args()))
{
    // ...
}

Мне не нравится, что тело метода зависит от индексов аргументов (когда, казалось бы, это не нужно) Есть ли более чистый способ достичь того, чего я хочу?


Я пробовал:

if(isset($previous)){}

if(!empty($previous)){}

if(null !== $previous){}

Ни то, ни другое не работает.

Возможные решения на данный момент:

if(func_num_args() == $num_params){}

if(array_key_exists($param_index, func_get_args())){}

// 5.4
if(isset(func_get_args()[$param_index])){}

// 5.4
if(func_num_args() == (new \ReflectionMethod(__CLASS__, __FUNCTION__))
    ->getNumberOfParameters()){}

@DaveRandom -- Итак, что-то в районе:

define('_NOPARAM', '_NOPARAM' . hash('sha4096', microtime()));

function foo($bar = _NOPARAM)
{
    // ...
}

@hoppa -- Use case:

$obj->set_something('some_key', $some_value, $previous) // set
    ->do_something_that_uses_some_key()
    ->set_something('some_key', $previous) // and reset
    ->do_something_that_uses_some_key()
    -> ...

Instead of:

$previous = $obj->get_something('some_key'); // get
$obj->set_something('some_key', $some_value) // set
    ->do_something_that_uses_some_key();
    ->set_something($previous) // and reset
    ->do_something_that_uses_some_key();
    -> ...
17
задан Dan Lugg 31 December 2012 в 17:00
поделиться