recibe - Probando argumentos opcionales en PHP
php objeto por referencia (2)
Extraído de los comentarios / discusión anterior:
Para verificar si se aprobó el argumento, tiene 2 opciones: verifique el valor del argumento con respecto a un valor (como lo hizo con nulo) o verifique el número de argumentos.
Si elige la primera opción, no hay ningún valor que no se pueda pasar desde fuera de la función, por lo que siempre habrá una posibilidad de falsos positivos (lo mismo que está sucediendo ahora con nulo). Sin embargo, el ejemplo de DaveRandom con una cadena aleatoria debería ser suficiente para la mayoría de los casos, pero lo veo como una exageración.
Creo que la segunda opción es la más limpia (rápida, legible, etc.). Como una pequeña mejora con respecto a lo que ya ha hecho con func_get_args
, usaría func_num_args
; de esta manera, comprobará el número de argumentos pasados, no los índices de argumentos.
Tengo algunos métodos de "establecimiento" en todas las clases y, por conveniencia, he agregado un parámetro opcional $previous
, que toma un argumento por referencia y lo llena con el valor existente antes de reemplazarlo con el nuevo. Por ejemplo:
public function set_value($key, $value, &$previous = null)
{
$previous = $this->get_value($key);
$this->_values[$key] = $value;
return $this;
}
Esto funciona bien; sin embargo, en algunas circunstancias, el método "captador" correspondiente requiere un poco de proceso y su ejecución incondicional es un desperdicio. Pensé que podría probar:
if(null !== $previous)
{
$previous = $this->get_value($key);
}
Sin embargo, esto no funciona, ya que a menudo la variable que se pasa como argumento para $previous
no se ha definido previamente en su alcance, y el valor predeterminado es nulo de todos modos. La única solución que he eliminado es:
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;
}
O, para una línea,
if(array_key_exists(2, func_get_args()))
{
// ...
}
No me gusta que el cuerpo del método dependa de los índices de los argumentos ( cuando parece que debería ser innecesario ) ¿Hay una forma más limpia de lograr lo que estoy buscando aquí?
He intentado:
if(isset($previous)){}
if(!empty($previous)){}
if(null !== $previous){}
Tampoco trabajo.
Posibles soluciones hasta el momento:
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 - Entonces, algo en el área de:
define(''_NOPARAM'', ''_NOPARAM'' . hash(''sha4096'', microtime()));
function foo($bar = _NOPARAM)
{
// ...
}
@hoppa - Caso de uso:
$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()
-> ...
En lugar de:
$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();
-> ...
posiblemente no cómo quería resolver su problema (probando argumentos opcionales), pero así es como lo implementaría:
public function set_value($key, $value)
{
$this->_values[$key] = $value;
return $this;
}
public function set_get_value($key, $value, &$previous)
{
$previous = $this->get_value($key);
$this->_values[$key] = $value;
return $this;
}
Ejemplo de caso de uso:
$obj->set_get_something(''some_key'', $some_value, $previous) // set AND get
->do_something_that_uses_some_key()
->set_something(''some_key'', $previous) // and reset
->do_something_that_uses_some_key()
-> ...
¿Por qué usar otra función?
Esta solución tiene algunas ventajas:
- El nombre es más explícito, menos confusión para otros codificadores.
- sin efectos secundarios ocultos
- resuelve su problema con variables (indefinidas) que ya tienen un valor
- sin sobrecarga de llamar a
func_num_args
, o alguna otra función "meta"
EDITAR: error tipográfico en el código.
EDIT 2: se eliminó el valor predeterminado de la función $ set_get_value () anterior (gracias a draevor)