web-dev-qa-db-fra.com

rendre commutateur utiliser === comparaison == comparaison dans PHP

Y a-t-il un moyen de faire en sorte que le code suivant utilise toujours un commutateur et retourne b not a? Merci!

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

En utilisant if, bien sûr, vous le feriez comme ceci:

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

Mais pour des exemples plus complexes, cela devient verbeux.

64
Aaron Yodaiken

Désolé, vous ne pouvez pas utiliser une comparaison === dans une instruction switch car, selon la documentation switch () :

Notez que switch/case fait perdre la comparaison.

Cela signifie que vous devrez trouver une solution de contournement. À partir de le tableau de comparaison lâche , vous pouvez utiliser le fait que NULL == "0" est faux en spécifiant le type:

<?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'
?>

Démo en direct

48
Peter Ajtai

Pas avec switch - cela ne fait que des comparaisons "lâches". Vous pouvez toujours le remplacer par un bloc if/else if, en utilisant ===.

7
Adam Wright

Vraisemblablement, vous activez la variable et attendez des entiers. Pourquoi ne pas simplement vérifier le statut entier de la variable au préalable en utilisant is_int($val)?

3
Matt Esch

J'ai eu le même problème dans un commutateur avec une chaîne contenant des nombres ("15.2" est égal à "15.20" dans un commutateur pour php)

J'ai résolu le problème en ajoutant une lettre avant le texte à comparer

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

make switch utilise === comparaison pas == comparaison en PHP

Malheureusement, switch utilise une comparaison approximative et, autant que je sache, il n’ya aucun moyen de changer cela.

1
quantumSoup

Nan. De la page de manuel :

Notez que switch/case fait perdre la comparaison

Si vous n'avez que deux conditions, utilisez une if comme votre deuxième exemple. Sinon, vérifiez d'abord NULL et activez les autres possibilités:

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

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

L'instruction switch en php ne fait que des comparaisons lâches (==) voir http://www.php.net/manual/en/control-structures.switch.php

Utilisez if/elseif/else si vous avez besoin de comparaisons strictes.

1
Esteban

Voici votre code d'origine dans une instruction switch "stricte":

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

Cela peut également gérer des instructions de commutateur plus complexes comme ceci:

switch(true) {
    case $var === null:
        return 'a';
        break;
    case $var === 4:
    case $var === 'foobar':
        return 'b';
    default:
        return 'c';
        break;
}
1
thespacecamel

Je viens d'utiliser 

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

Je pense que cela semble toujours très lisible si le commentaire commençant par // est laissé (et ceux qui commencent par # sont probablement mieux supprimés).

1
raveren

Ce n'est pas possible.

Vous pouvez cependant mettre les instructions if inside switch:

switch($var) {
    // Loose cases here

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

        // Fall through

    default:
        return 'b';
}

Ou simplement:

switch($var) {
    // Loose cases here

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

        return 'b';
}
0
strager

L’un des meilleurs moyens est de vérifier la valeur NULL en utilisant is_null

<?php
echo getValue();
function getValue()
{
    $var = 0;   
    switch(true) {
        case is_null($var) : return 'a'; break;
        default : return 'b'; break;
    }
}
?>
0
Prem Kumar Maurya

Vous pouvez également activer le type de la variable:

switch (gettype($var)) {
...
}
0
greg

Si vous voulez tester à la fois valeur _ et type de votre variable, créez un nouveau variable de chaîne contenant les deux informations et comparez-le avec vos différents scénarios (par concaténation). ) cela devrait fonctionner pour votre cas si vous implémentez tous les types possibles (selon gettype () documentation ), exemple:

<?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'
?>

Créez une classe semblable à une assertion et mettez-y toute la logique que vous voulez; tant que les méthodes "true" renvoient $this (et rien d'autre pour éviter les faux positifs).

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

Ou vous pouvez placer votre commutateur dans la classe actuelle:

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"

Bien sûr, vous voudrez peut-être réévaluer ce que vous voulez faire avec ce que vous vérifiez et utiliser à la place une vraie bibliothèque de validation.

0
user1718888

Extrapolant à partir de votre exemple de code, je suppose que vous avez un tas de cas réguliers et un cas spécial (ici, null).

Le plus simple que je puisse comprendre est de traiter ce cas avant le changement:

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

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

Peut-être aussi ajouter un commentaire pour rappeler que null correspondrait de manière inattendue au cas 0 (le contraire, 0 correspondrait à un cas null).

0
Gras Double