Der beste Weg, einer Variablen einen Standardwert zu geben (simuliere Perl ||, || =)

134

Ich liebe es, so etwas in Perl $foo = $bar || $bazzu tun: zuzuweisen $baz, $fooob $bares leer oder undefiniert ist. Sie haben auch $foo ||= $bletchwelche nur zuweisen $bletch, $foowenn $foonicht definiert oder leer ist.

Der ternäre Bediener ist in dieser Situation mühsam und ermüdend. Sicherlich gibt es in PHP eine einfache, elegante Methode?

Oder ist die einzige Antwort eine benutzerdefinierte Funktion, die isset () verwendet?

Tom Auger
quelle
1
Übrigens sind die Perl-Operatoren mit der gewünschten Funktionalität //und //=und sie existieren ab Perl v5.10.0. Das Original ||und der ||=Test auf logischen Wert, nicht auf Definiertheit.
Palec
@Palec, warum sollte eine 4-jährige Frage mit 29 positiven Stimmen als Duplikat einer 1-jährigen Frage mit 6 positiven Stimmen identifiziert werden (die selbst als Duplikat einer anderen Frage markiert wurde?). Ich denke, es ist sehr wertvoll, dies beizubehalten Frage, da der Titel allgemeiner ist (verweist nicht auf die Antwort, dh: isset ()).
Tom Auger
Sie sind klare und genaue Duplikate. Es gibt zu, dass ich nicht viel darüber nachgedacht habe, welches das Original sein sollte, ich war mitten in etwas anderem, eine Verbindung zwischen den beiden herzustellen war das Ziel. Meine VTC zurückziehen.
Palec
Ein genaues Duplikat, das (IMO fälschlicherweise) als Duplikat einer anderen Frage markiert ist: PHP-Abkürzung für isset ()?
Palec

Antworten:

130

In PHP 7 haben wir endlich die Möglichkeit, dies elegant zu tun. Es wird als Null-Koaleszenzoperator bezeichnet . Sie können es so verwenden:

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

Dies entspricht

$name = isset($_GET['name']) ? $_GET['name']:'john doe';
jpschroeder
quelle
14
Ich würde behaupten, der Raumschiffbetreiber hat auch Verdienst.
Mariano
3
Ich dachte, Mariano würde an unseren Beinen ziehen, aber nein, es ist eine Sache <=>und ziemlich genau zu booten!
HPWD
1
Beachten Sie, dass sich der Null-Koaleszenz-Operator anders als der bedingte Operator verhält, da er für einen nullWert spezifisch ist. Wenn zum Beispiel $_GET['name']eine leere Zeichenfolge festgelegt ist, würde die erste Zeile eine leere Zeichenfolge zurückgeben, aber wir könnten "john doe" mit verwenden $_GET['name'] ? $_GET['name'] : 'john doe'.
VPhantom
211

PHP 5.3 hat einen Kurzoperator ?::

$foo = $bar ?: $baz;

Was zugewiesen wird, $barwenn es kein leerer Wert ist (ich weiß nicht, wie sich dies in PHP von Perl unterscheiden würde), andernfalls $bazund dasselbe wie in Perl und älteren Versionen von PHP:

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

PHP verfügt jedoch nicht über einen zusammengesetzten Zuweisungsoperator (dh kein Äquivalent zu Perl ||=).

Außerdem macht PHP Rauschen, wenn $bares nicht eingestellt ist, es sei denn, Sie schalten Benachrichtigungen aus. Es gibt auch einen semantischen Unterschied zwischen isset()und empty(). Ersteres gibt false zurück, wenn die Variable nicht vorhanden ist oder auf gesetzt ist NULL. Letztere gibt true zurück , wenn es nicht existiert, oder ist auf 0, '', falseoder NULL.

BoltClock
quelle
2
+1 Um mir eine weitere großartige Funktion von 5.3 vorzustellen, die ich auf meinen RHEL5 / PHP5.1.2-Servern verpasse.
Michael Berkowski
Ich denke du meinst The first returnsstatt The secondin deinem vorletzten Satz.
Toto
21
Beachten Sie, dass PHP Benachrichtigungen darüber ausgibt, wenn Ihre Variable undefiniert ist. Dies ist leider kein Ersatz für $var = isset($var) ? $var : 'default value'; Es heißt, dass in der Antwort ... nur noch einmal darauf hingewiesen wird für jeden, der es überfliegt. :-D
Brad
6
Ist es schlecht, $ var = @ $ var zu tun ?: 'Standardwert'; Wenn ja warum? Angesichts der Tatsache, dass der einzige "Fehler" sein könnte, dass $ var nicht gesetzt ist und es uns egal ist, ob $ var nicht gesetzt ist ...
Codemonkey
8

Danke für all die tollen Antworten!

Für alle anderen, die wegen einer möglichen Alternative hierher kommen, sind hier einige Funktionen, die helfen, die Langeweile aus solchen Dingen herauszuholen.

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

Beispiele:

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

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

Ich bin sicher, dass diese verbessert werden können.

Tom Auger
quelle
7

Eine gängige Redewendung, um mit älteren PHP-Versionen kompatibel zu bleiben, ist:

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

Dies funktioniert für Werte, die im booleschen Kontext ausgewertet werden können. Der Vorteil hierbei ist, dass Sie auch das Debugging e_notice erhalten, falls die Variable undefiniert ist.

Mario
quelle
Wird eine Benachrichtigung nicht gesendet, $bool ? $bool : "default"wenn sie $boolnicht definiert ist?
BoltClock
Klar, das ist das gleiche. Ich nahm an, dass sich OP auf bezieht isset($var) ? $var : DEFAULT. Aber es hört sich so an, als würde er sie trotzdem meiden wollen.
Mario
6

In PHP vor 7. * kann man ?: Für eine undefinierte Variable verwenden, deren Fehler lokal unterdrückt werden mit @:

$foo = @$bar ?: $baz;
AndreyS Scherbakov
quelle
0

Dies ist ein weiteres gutes Format für den issetFall

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

Ein weiterer einfacher Weg, der Ihnen mehr Kontrolle gibt, da Sie gleichzeitig weitere Bedingungen hinzufügen und einer anderen Variablen zuweisen können

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

Bassem Shahin
quelle
0

Eine mögliche Lösung: defaultFor ()

Sofern wir keine Werkslösung haben (was in der Tat sehr ärgerlich ist), würde ich den folgenden kleinen Helfer empfehlen. Es macht den Job in den meisten Fällen:


    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

Ich hoffe, das kommt dem nahe, was Sie erreichen wollten. Es gibt Ihnen keine Hinweise, wenn Sie es mit einer nicht vorhandenen Variablen verwenden, und es ist sehr praktisch. Sicherlich hat es einen Nachteil: Der Standardwert wird immer im Voraus berechnet. Verwenden Sie ihn daher nicht mit etwas Schwerem als zweitem Parameter, wie z. B. einem file_get_contents oder etwas anderem. In diesen Fällen sind Sie mit der Ausgabe besser dran.

dkellner
quelle