Meilleure façon de donner une valeur par défaut à une variable (simuler Perl ||, || =)


134

J'aime faire ce genre de chose en Perl: $foo = $bar || $bazattribuer $bazà $foosi $barest vide ou non défini. Vous avez également $foo ||= $bletchqui n'attribuer $bletchà $foosi $foon'est pas défini ou vide.

L'opérateur ternaire dans cette situation est fastidieux et ennuyeux. Il existe sûrement une méthode simple et élégante disponible en PHP?

Ou la seule réponse est-elle une fonction personnalisée qui utilise isset ()?



1
BTW les opérateurs Perl avec les fonctionnalités souhaitées sont //et //=et ils existent à partir de Perl v5.10.0. L'original ||et ||=teste la valeur logique, pas la définition.
Palec

@Palec, pourquoi une question de 4 ans avec 29 votes positifs serait identifiée comme un duplicata d'une question de 1 an avec 6 votes positifs (qui elle-même a été marquée comme un double d'une autre question?) Je pense qu'il est très utile de garder cela question, car le titre est plus générique (ne fait pas référence à la réponse c'est-à-dire: isset ()).
Tom Auger

Ce sont des doublons clairs et exacts. J'avoue que je ne pensais pas beaucoup à laquelle devrait être l'original, j'étais au milieu de quelque chose d'autre, faire un lien entre les deux était le but. Rétracter mon VTC.
Palec

Un duplicata exact, marqué (IMO à tort) comme duplicata d'une autre question: raccourci PHP pour isset ()?
Palec

Réponses:


131

En PHP 7, nous avons enfin un moyen de faire cela avec élégance. Il est appelé l' opérateur de fusion Null . Vous pouvez l'utiliser comme ceci:

$name = $_GET['name'] ?? 'john doe';

Cela équivaut à

$name = isset($_GET['name']) ? $_GET['name']:'john doe';

14
Je dirais que l' opérateur du vaisseau spatial a également du mérite.
Mariano

3
Je pensais que Mariano nous tirait les jambes mais non, c'est une chose <=>et assez précise pour démarrer!
HPWD

1
Notez que l'opérateur de fusion nul se comporte différemment de l'opérateur conditionnel, car il est spécifique à une nullvaleur. Par exemple, si $_GET['name']est défini sur une chaîne vide, la première ligne renverrait une chaîne vide, mais nous pourrions renvoyer "john doe" en utilisant $_GET['name'] ? $_GET['name'] : 'john doe'.
VPhantom

211

PHP 5.3 a un ?:opérateur de raccourci :

$foo = $bar ?: $baz;

Ce qui attribue $barsi ce n'est pas une valeur vide (je ne sais pas en quoi cela serait différent en PHP de Perl), sinon $baz, et c'est la même chose en Perl et les anciennes versions de PHP:

$foo = $bar ? $bar : $baz;

Mais PHP n'a pas d'opérateur d'assignation composé pour cela (c'est-à-dire pas d'équivalent de Perl ||=).

De plus, PHP fera du bruit s'il $barn'est pas défini, sauf si vous désactivez les notifications. Il existe également une différence sémantique entre isset()et empty(). Le premier retourne false si la variable n'existe pas ou est définie sur NULL. Ce dernier retourne vrai s'il n'existe pas ou est réglé sur 0, '', falseou NULL.


2
+1 Pour m'avoir présenté une autre fonctionnalité intéressante de 5.3, je passe à côté de mes serveurs RHEL5 / PHP5.1.2.
Michael Berkowski

Je suppose que vous voulez dire The first returnsau lieu de The seconddans votre avant-dernière phrase.
Toto

21
Notez que si votre variable n'est pas définie, PHP lèvera des notifications à son sujet. Ceci, malheureusement, ne remplace pas $var = isset($var) ? $var : 'default value'; Cela dit que dans la réponse ... il suffit de le signaler à tous ceux qui l'écrément. :-D
Brad

6
Est-ce mal de faire $ var = @ $ var?: 'Valeur par défaut'; Si oui, pourquoi? Étant donné que la seule "erreur" pourrait être que $ var n'est pas défini, et que nous ne nous soucions pas si $ var n'est pas défini ...
Codemonkey

8

Merci pour toutes les bonnes réponses!

Pour quiconque vient ici pour une alternative possible, voici quelques fonctions qui aident à réduire l'ennui de ce genre de choses.

function set_if_defined(&$var, $test){
    if (isset($test)){
        $var = $test;
        return true;
    } else {
        return false;
    }
}

function set_unless_defined(&$var, $default_var){
    if (! isset($var)){
        $var = $default_var;
        return true;
    } else {
        return false;
    }
}

function select_defined(){
    $l = func_num_args();
    $a = func_get_args();
    for ($i=0; $i<$l; $i++){
        if ($a[$i]) return $a[$i];
    }
}

Exemples:

// $foo ||= $bar;
set_unless_defined($foo, $bar);

//$foo = $baz || $bletch
$foo = select_defined($baz, $bletch);

Je suis sûr que ceux-ci peuvent être améliorés.


7

Un idiome courant pour rester compatible avec les anciennes versions de PHP est:

 $var = $bool   or   $var = "default";
 // If I use it, then only with excessive spaces for clarity.

Cela fonctionne pour les valeurs qui peuvent être évaluées dans un contexte booléen. L'avantage ici est qu'il vous donne également un e_notice de débogage si la variable n'est pas définie.


Un avis n'est-il pas émis avec $bool ? $bool : "default"si $booln'est pas défini?
BoltClock

Bien sûr, c'est la même chose. J'ai supposé que OP faisait référence isset($var) ? $var : DEFAULT. Mais on dirait qu'il veut les éviter de toute façon.
mario

6

En PHP antérieur à 7. *, on peut utiliser?: Pour une variable indéfinie ayant des erreurs supprimées localement avec un @:

$foo = @$bar ?: $baz;

0

c'est un autre bon format pour le issetboîtier

isset($foo) || $foo= $bar;

un autre moyen simple et vous donnera plus de contrôle car vous pouvez ajouter plus de conditions et assigner à une autre variable en même temps

$foo = (isset($oData['foo']))?$bar['foo']:'default value';


0

Une solution possible: defaultFor ()

À moins d'avoir une solution d'usine (ce qui est en effet très ennuyeux), je recommanderais le petit assistant suivant. Il fait le travail dans la plupart des cas:


    function defaultFor(&$x,$default=null) {
        if(!isset($x)) $x = $default;
    }

    //--------------------  Now you can do this: --------------

    defaultFor($a,"Jack");  // if $a is not set, it will be "Jack"
    defaultFor($x);         // no more notices for $x but keep it !isset

J'espère que c'est proche de ce que vous vouliez réaliser. Il ne vous donnera aucun avis si vous l'utilisez avec une variable inexistante, et c'est assez pratique. Cela a sûrement un inconvénient: la valeur par défaut est toujours calculée à l'avance, alors ne l'utilisez pas avec quelque chose de lourd comme deuxième paramètre, comme un file_get_contents ou quelque chose. Dans ces cas, il vaut mieux émettre.


0

Je pense en général faire quelque chose comme ça:

$foo = $bar || $baz;

est une mauvaise idée, sauf si $baret $bazsont tous les deux des booléens. S'ils ne sont pas:

$bar = 10;
$baz = 11;

alors la question devient: qu'est-ce qui détermine si quelque chose est vrai ou faux? La plupart des gens s'attendraient probablement à ce que zéro soit faux et que tout le reste soit vrai. Mais avec certains langages (par exemple Ruby), seulement falseet nilsont faux, ce qui signifie les deux 0et 1serait vrai. En raison de cette ambiguïté entre les langues, je pense qu'il vaut mieux être explicite dans ces cas:

if ($bar !== 0) {
   $foo = $bar;
} else {
   $foo = $baz;
}

ou:

$foo = $bar !== 0 ? $bar : $baz;
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.