51 votes

Empiler plusieurs opérateurs ternaires en PHP

Voici ce que j'ai écrit :

 $Myprovince = (
($province == 6) ? "city-1" :
($province == 7) ? "city-2" :
($province == 8) ? "city-3" :
($province == 30) ? "city-4" : "out of borders"
);

Mais pour chaque champ, j'ai obtenu la valeur city-4 . Je veux utiliser des opérateurs ternaires au lieu de switch/if parce que je veux expérimenter et voir comment cela se passerait.

Quel est le problème avec ce code ?

113voto

codaddict Points 154968

D'autres ont déjà suggéré la bonne façon de procéder mais si vous voulez vraiment utiliser l'opérateur ternaire, vous devez utiliser les parenthèses comme :

$province = 7;
 $Myprovince = (
 ($province == 6) ? "city-1" :
  (($province == 7) ? "city-2" :
   (($province == 8) ? "city-3" :
    (($province == 30) ? "city-4" : "out of borders")))
 );

Lien actualisé

38voto

Felix Kling Points 247451

L'opérateur ternaire est évalué de gauche à droite. Donc, si vous ne groupez pas les expressions correctement, vous obtiendrez un résultat inattendu.

Le conseil de PHP est [docs] :

Il est recommandé d'éviter d'"empiler" les expressions ternaires. Le comportement de PHP lorsqu'il utilise plus d'un opérateur ternaire dans une même déclaration n'est pas évident.

Votre code est en fait évalué comme :

(
    (
        (
            $province == 6 ? "city-1" : $province == 7
        ) ? "city-2" : 
        $province == 8
    ) ? "city-3" : $province == 30
) ? "city-4" : "out of borders";

où il devrait être

$province == 6 ? "city-1" : (
    $province == 7 ? "city-2" : (
        $province == 8 ? "city-3" : (
           $province == 30 ? "city-4" : "out of borders"
        )
    )
);

Ce code peut sembler parfait, mais quelqu'un le lira et aura besoin de plus de temps que nécessaire pour comprendre ce qu'il fait.


Vous seriez mieux avec quelque chose comme ça :

$map = array( 6 = >'city-1', 
              7 => 'city-2', 
              8 => 'city-3', 
             30 => 'city-4');

$Myprovince = "out of borders";

if(array_key_exists($province, $map)) {
    $Myprovince = $map[$province];
}

Ou comme @Jonah mentionné dans son commentaire :

$Myprovince = isset($map[$province]) ? $map[$province] : 'out of borders';

19voto

Marc B Points 195501

N'abusez pas de l'opérateur ternaire pour ce genre de choses. Cela rend le débogage presque impossible à suivre. Pourquoi ne pas faire quelque chose comme

switch($province) {
    case 6: $Myprovince = "city-1"; break;
    case 7: ...
}

ou simplement des chaînages if/then/else

if ($province == 6) {
     $Myprovince = "city-1";
} elseif ($province = ...) {
   ...
}

15voto

arnorhs Points 6107

Certaines personnes ont suggéré d'utiliser une instruction switch ou une instruction if/else. Mais j'utiliserais plutôt un tableau, pour faciliter la maintenance et la lecture :

$provinces = array (
    6 => 'city-1',
    7 => 'city-2',
    8 => 'city-3',
    30 => 'city-4'
);

// then you can call:

$Myprovince = isset($provinces[$province]) ? $provinces[$province] : 'out of borders';

Pourquoi ?

Le code sera probablement plus facile à gérer à terme. Peut-être voudrez-vous un jour ajouter les correspondances entre les provinces et les villes à partir de la base de données, etc. Ce sera difficile à maintenir avec un tas d'instructions switch/case.

7voto

Noah Points 378

Je comprends qu'il s'agit d'une question sur PHP, mais comme il s'agit d'un exercice éducatif, j'ai pensé que vous seriez intéressé d'apprendre que Ruby et Javascript se comportent réellement comme vous l'attendez.

Ruby :

ree-1.8.7-2012.02 :009 > def foo x
ree-1.8.7-2012.02 :010?>   x == 1 ? "city 1" : x == 2 ? "city 2" : "out of borders"
ree-1.8.7-2012.02 :011?>   end
 => nil
ree-1.8.7-2012.02 :012 > foo 1
 => "city 1"
ree-1.8.7-2012.02 :013 > foo 2
 => "city 2"
ree-1.8.7-2012.02 :014 > foo 3
 => "out of borders"

Javascript :

> function f(x) { return x == 1 ? "city 1" : x == 2 ? "city 2" : "out of borders"; }
undefined
> f(1)
"city 1"
> f(2)
"city 2"
> f(3)
"out of borders"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X