Tester les arguments optionnels en PHP

j'ai quelques méthodes "setter" à travers les classes, et pour plus de commodité j'ai ajouté un paramètre optionnel $previous, qui prend un argument par référence et le remplit avec la valeur existante avant de la remplacer par la nouvelle. Par exemple:

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

cela fonctionne très bien; cependant, dans certaines circonstances, la méthode "getter" correspondante est un processus de bits intensif, et l'exécuter inconditionnellement est un gaspillage. J'ai pensé que j'ai pu tester:

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

Ce n'est pas le travail cependant, aussi souvent la variable passée que l'argument pour $previous n'a pas été défini dans son scope, et par défaut à null de toute façon. La seule solution que j'ai piraté est:

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;
}

Ou, pour une ligne:

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

Je n'aime pas que le corps de la méthode soit dépendant des indices des arguments (quand il semble qu'il devrait être inutile) y a-t-il une façon plus propre d'atteindre ce que je cherche ici?


j'ai essayé:

if(isset($previous)){}

if(!empty($previous)){}

if(null !== $previous){}

Ni travail.

solutions possibles jusqu'à présent:

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 -- donc, quelque chose dans le domaine de:

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

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

@hoppa -- cas d'Utilisation:

$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()
    -> ...

au Lieu 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();
    -> ...
17
demandé sur Dan Lugg 2011-12-19 17:55:53

2 réponses

peut-être pas comment vous vouliez résoudre votre problème (tester en quelque sorte les arguments optionnels), mais c'est comme ça que je l'implémenterais:

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;
}

de cas d'Utilisation exemple:

$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()
    -> ...

Pourquoi utiliser une autre fonction?

Cette solution présente quelques avantages:

  1. le nom est plus explicite, moins de confusion pour les autres codeurs
  2. pas d'effets secondaires cachés
  3. résout votre problème avec (Non défini) variables ayant déjà une valeur
  4. pas de frais généraux de l'appel à func_num_args, ou une autre fonction" meta"

EDIT: code typographique.

EDIT 2: suppression de la valeur par défaut de$set_get_value() fonction (grâce à draevor)

3
répondu catchmeifyoutry 2011-12-19 17:49:33

extrait des commentaires / discussions ci-dessus:

afin de vérifier si l'argument était passé, vous avez 2 options - vérifier la valeur de l'argument contre une valeur (comme vous l'avez fait avec null), ou vérifier le nombre d'arguments.

si vous allez avec la première option, il n'y a aucune valeur qui ne peut pas être transmise depuis l'extérieur de la fonction, donc il y aura toujours une chance pour les faux positifs (la même chose qui se produit maintenant avec null). L'exemple de DaveRandom avec une chaîne aléatoire devrait suffire pour la plupart des cas, mais je le vois comme une exagération.

je pense que la deuxième option est la plus propre (rapide, lisible, etc). Comme une petite amélioration par rapport à ce que vous avez déjà fait avec func_get_args, je voudrais utiliser func_num_args - de cette façon vous vérifierez le nombre d'arguments passés, pas les indices d'argument.

2
répondu deviousdodo 2011-12-19 17:16:02