Schalter verwenden === Vergleich nicht == Vergleich In PHP

78

Gibt es sowieso eine Möglichkeit, damit der folgende Code noch einen Schalter verwendet und bnicht zurückgibt a? Vielen Dank!

$var = 0;
switch($var) {
    case NULL : return 'a'; break;
    default : return 'b'; break;
}

Wenn Sie if-Anweisungen verwenden, würden Sie dies natürlich folgendermaßen tun:

$var = 0;
if($var === NULL) return 'a';
else return 'b';

Bei komplexeren Beispielen wird dies jedoch ausführlich.

Aaron Yodaiken
quelle

Antworten:

55

Leider können Sie keinen ===Vergleich in einer switch-Anweisung verwenden, da gemäß der switch () -Dokumentation :

Beachten Sie, dass Schalter / Gehäuse den Vergleich verlieren.

Dies bedeutet, dass Sie eine Problemumgehung finden müssen. Aus der Tabelle mit den losen Vergleichen können Sie die Tatsache nutzen, dass die NULL == "0"Typumwandlung falsch ist:

<?php
$var = 0;
switch((string)$var) 
{
    case "" : echo 'a'; break; // This tests for NULL or empty string   
    default : echo 'b'; break; // Everything else, including zero
}
// Output: 'b'
?>

Live-Demo

Peter Ajtai
quelle
1
Nun, es gibt andere Umstände (nicht nur mit NULL-Werten), mit denen ich gerne arbeiten würde.
Aaron Yodaiken
18

Hier ist Ihr Originalcode in einer "strengen" switch-Anweisung:

switch(true) {
    case $var === null:
        return 'a';
    default:
        return 'b';
}

Dies kann auch komplexere switch-Anweisungen wie diese verarbeiten:

switch(true) {
    case $var === null:
        return 'a';
    case $var === 4:
    case $var === 'foobar':
        return 'b';
    default:
        return 'c';
}
Thespacecamel
quelle
8

Nicht mit switch- es werden nur sogenannte "lose" Vergleiche durchgeführt. Sie können es jederzeit durch einen if/else ifBlock ersetzen , indem Sie ===.

Adam Wright
quelle
Beziehen Sie sich auf Ihre Erfahrung oder Dokumentation? Wenn dies der Fall ist, posten Sie bitte einen Link
TMS
1
Sie können dies tatsächlich mit tun switch(siehe meine Antwort), obwohl ich denke, dass if-elsedies für diesen bestimmten Job besser ist.
Dave Random
Viele gute Antworten, sorry, ich kann nur 1 auswählen. Ich ging mit if / elseif danke an alle.
Yar Matie
Eigentlich nicht "immer" :) Was ist, wenn nicht alle Fallblöcke breakoder haben return?
Sturm
3

Vermutlich schalten Sie die Variable ein und erwarten ganze Zahlen. Warum nicht einfach vorher den Integer-Status der Variablen überprüfen is_int($val) ?

Matt Esch
quelle
3

Ich hatte das gleiche Problem in einem Schalter mit Zeichenfolge, die Zahlen enthält ("15.2" ist gleich "15.20" in einem Schalter für PHP)

Ich habe das Problem gelöst, indem ich vor dem zu vergleichenden Text einen Buchstaben hinzugefügt habe

$var = '15.20';
switch ('#'.$var) {
    case '#15.2' :
      echo 'wrong';
    break;
    case '#15.20' :
      echo 'right';
    break;
}
caiofior
quelle
1

Schalter verwenden === Vergleich nicht == Vergleich In PHP

switchVerwendet leider einen losen Vergleich und soweit ich weiß gibt es keine Möglichkeit das zu ändern.

quantumSoup
quelle
1

Ich benutze nur

$var === null and $var = -1; // since switch is not type-safe
switch ( $var ) {
    case 0:
        # this tests for zero/empty string/false
        break;
    case -1:
        # this tests for null
        break;
}

Ich denke, das sieht immer noch sehr gut lesbar aus, wenn der Kommentar, der mit beginnt, zurückgelassen //wird (und diejenigen, die mit beginnen, #werden wahrscheinlich am besten gelöscht).

Raveren
quelle
1

Nee. Von der Handbuchseite :

Beachten Sie, dass Schalter / Gehäuse den Vergleich verlieren .

Wenn Sie nur zwei Bedingungen haben, verwenden Sie eine ifwie Ihr zweites Beispiel. Andernfalls prüfen Sie NULLzuerst und schalten Sie die anderen Möglichkeiten ein:

if (is_null($var))
{
  return 'a';
}

switch ($var)
{
    // ...
}
Daniel Vandersluis
quelle
1

Wenn Sie Ihren Beispielcode extrapolieren, haben Sie wahrscheinlich eine Reihe von regulären Fällen und einen Sonderfall (hier null).

Das Einfachste, was ich herausfinden kann, ist, diesen Fall vor dem Wechsel zu behandeln:

if ($value === null) {
    return 'null';
}

switch ($value) {
    case 0:
        return 'zero';
    case 1:
        return 'one';
    case 2:
        return 'two';
}

Fügen Sie möglicherweise auch einen Kommentar hinzu, an den Sie sich erinnern sollten, nulldass er unerwartet zum 0Fall passt (auch im Gegenteil, 0würde zu einem nullFall passen ).

Gras Double
quelle
1

Ja. Unter PHP 8 können Sie dies mit matchAnweisung tun .

Im Gegensatz zu switch ist der Vergleich eher eine Identitätsprüfung (===) als eine schwache Gleichheitsprüfung (==). Übereinstimmungsausdrücke sind ab PHP 8.0.0 verfügbar.

Siehe hier: https://www.php.net/manual/en/control-structures.match.php

$var=0;
echo match ($var) {
    NULL=> 'a',
    default => 'b'
};
zvi
quelle
0

Das ist nicht möglich.

Sie können jedoch setzen die ifAussagen innerhalb der switch:

switch($var) {
    // Loose cases here

    case 0:
        if($var === NULL) {
            return 'a';
        }

        // Fall through

    default:
        return 'b';
}

Oder einfach:

switch($var) {
    // Loose cases here

    default:
        if($var === NULL) {
            return 'a';
        }

        return 'b';
}
Strager
quelle
7
Warum sollte man sich an diesem Punkt mit dem Schalter beschäftigen? Sie könnten sogar `switch (true) {case $ var === null: ...}
ircmaxell
1
@ircmaxell, ich nahm an, dass das OP eine Durchfalllogik oder einen anderen Grund haben möchte switch, der manchmal über eine strenge Überprüfung hinausgeht.
Strager
0

Sie können auch den Typ der Variablen einschalten:

switch (gettype($var)) {
...
}
greg
quelle
Schlechte Idee - Aus den Dokumenten:Never use gettype() to test for a certain type, since the returned string may be subject to change in a future version. In addition, it is slow too, as it involves string comparison. Instead, use the is_* functions.
Peter Ajtai
Wenn sich gettype () ändert, wird die Funktion unbrauchbar und die Sprache weniger zuverlässig. Die Verwendung von is_ * beantwortet die Frage zum Switch nicht. Für den Rest stimme ich zu :)
Greg
0

Eine der besten Möglichkeiten besteht darin, den NULL-Wert mithilfe von zu überprüfen is_null

<?php
echo getValue();
function getValue()
{
    $var = 0;   
    switch(true) {
        case is_null($var) : return 'a'; break;
        default : return 'b'; break;
    }
}
?>
Prem Kumar Maurya
quelle
1
Das Beste ist jedoch, dass === nullunnötiger Funktionsaufruf-Overhead vermieden wird.
Antti29
0

Erstellen Sie eine Assertions-ähnliche Klasse und fügen Sie die gewünschte Logik ein. solange "wahre" Methoden zurückkehren $this(und nichts anderes, um Fehlalarme zu vermeiden).

class Haystack
{
    public $value;

    public function __construct($value)
    {
        $this->value = $value;
    }

    public function isExactly($n)
    {
        if ($n === $this->value)
            return $this;
    }
}

$var = new Haystack(null);

switch ($var) {
    case $var->isExactly(''):
        echo "the value is an empty string";
        break;

    case $var->isExactly(null):
        echo "the value is null";
        break;
}

Oder Sie können Ihren Schalter in die eigentliche Klasse stellen:

class Checker
{
    public $value;

    public function __construct($value)
    {
        $this->value = $value;
    }

    public function isExactly($n)
    {
        if ($n === $this->value)
            return $this;
    }

    public function contains($n)
    {
        if (strpos($this->value, $n) !== false)
            return $this;
    }

    public static function check($str)
    {
        $var = new self($str);

        switch ($var) {
            case $var->isExactly(''):
                return "'$str' is an empty string";
            case $var->isExactly(null):
                return "the value is null";
            case $var->contains('hello'):
                return "'$str' contains hello";
            default:
                return "'$str' did not meet any of your requirements.";
        }
    }
}

var_dump(Checker::check('hello world'));   # string(28) "'hello world' contains hello"

Natürlich möchten Sie an diesem Punkt möglicherweise neu bewerten, was Sie mit dem, was Sie überprüfen, tun möchten, und stattdessen eine echte Validierungsbibliothek verwenden.

user1718888
quelle
0

Wenn Sie sowohl den Wert als auch den Typ Ihrer Variablen testen möchten , erstellen Sie eine neue Zeichenfolgenvariable, die beide Informationen enthält, und vergleichen Sie sie mit Ihren verschiedenen Szenarien (durch Verkettung). Dies sollte für Ihren Fall funktionieren, wenn Sie alle möglichen Typen implementieren (gemäß gettype ( ) Dokumentation ), Beispiel:

<?php
    $var= 9999;
    $valueAndTypeOfVar = (string)$var.' '.gettype($var);
    switch($valueAndTypeOfVar) {
        case "$var boolean" : echo 'a'; break;
        case "$var integer" : echo 'b'; break; 
        case "$var double" : echo 'c'; break;
        case "$var string" : echo 'd'; break; 
        case "$var array" : echo 'e'; break;
        case "$var object" : echo 'f'; break; 
        case "$var resource" : echo 'g'; break;
        case "$var NULL" : echo 'h'; break; 
        case "$var unknown type" : echo 'i'; break; 
        default: echo 'j'; break;
    }

   // Outputs: 'b'
?>
Mohamed Ayoub BENJELLOUN
quelle