## Opérateurs de comparaison

Les opérateurs de comparaison, comme leur nom l'indique, permettent de comparer deux valeurs. Il est également recommandé de consulter les tables de comparaisons de types, car elles montrent des exemples de beaucoup de types de comparaisons.

Opérateurs de comparaison
Exemple | Nom | Résultat
--- | --- | ---
$a == $b | Égal | `true` si $a est égal à $b après le transtypage.
$a === $b | Identique | `true` si $a est égal à $b et qu'ils sont de même type.
$a != $b | Différent | `true` si $a est différent de $b après le transtypage.
$a <> $b | Différent | `true` si $a est différent de $b après le transtypage.
$a !== $b | Différent | `true` si $a est différent de $b ou bien s'ils ne sont pas du même type.
$a < $b | Plus petit que | `true` si $a est strictement plus petit que $b.
$a > $b | Plus grand que | `true` si $a est strictement plus grand que $b.
$a <= $b | Inférieur ou égal | `true` si $a est plus petit ou égal à $b.
$a >= $b | Supérieur ou égal | `true` si $a est plus grand ou égal à $b.
$a <=> $b | Combiné | Un entier inférieur, égal ou supérieur à zéro lorsque $a est inférieur, égal, ou supérieur à $b respectivement.

Si les deux opérandes sont des chaînes numériques, ou si un opérande est un nombre et l'autre est une chaîne numérique, alors la comparaison sera effectuée numériquement. Ces règles s'appliquent également à l'instruction switch. La conversion de type n'intervient pas lorsque la comparaison est `===` ou `!==` vu que ceci engendre aussi bien une comparaison de type que de valeur.

Avertissement

Antérieur à PHP 8.0.0, si une string est comparée à un nombre ou à une chaîne numérique alors la string sera convertie en un nombre avant d'effectuer la comparaison. Ceci peut mener à des résultats surprenants comme le montre l'exemple suivant :

    <?php
    var_dump(0 == "a");
    var_dump("1" == "01");
    var_dump("10" == "1e1");
    var_dump(100 == "1e2");

    switch ("a") {
    case 0:
        echo "0";
        break;
    case "a":
        echo "a";
        break;
    }
    ?>

Résultat de l'exemple ci-dessus en PHP 7 :

    bool(true)
    bool(true)
    bool(true)
    bool(true)
    0

Résultat de l'exemple ci-dessus en PHP 8 :

    bool(false)
    bool(true)
    bool(true)
    bool(true)
    a

Exemple #1 Opérateurs de comparaison

    <?php
    // Entiers
    echo 1 <=> 1, ' '; // 0
    echo 1 <=> 2, ' '; // -1
    echo 2 <=> 1, ' '; // 1

    // Nombres flottants
    echo 1.5 <=> 1.5, ' '; // 0
    echo 1.5 <=> 2.5, ' '; // -1
    echo 2.5 <=> 1.5, ' '; // 1

    // Chaînes de caractères
    echo "a" <=> "a", ' '; // 0
    echo "a" <=> "b", ' '; // -1
    echo "b" <=> "a", ' '; // 1

    echo "a" <=> "aa", ' '; // -1
    echo "zz" <=> "aa", ' '; // 1

    // Tableaux
    echo [] <=> [], ' '; // 0
    echo [1, 2, 3] <=> [1, 2, 3], ' '; // 0
    echo [1, 2, 3] <=> [], ' '; // 1
    echo [1, 2, 3] <=> [1, 2, 1], ' '; // 1
    echo [1, 2, 3] <=> [1, 2, 4], ' '; // -1

    // Objets
    $a = (object) ["a" => "b"];
    $b = (object) ["a" => "b"];
    echo $a <=> $b, ' '; // 0

    $a = (object) ["a" => "b"];
    $b = (object) ["a" => "c"];
    echo $a <=> $b, ' '; // -1

    $a = (object) ["a" => "c"];
    $b = (object) ["a" => "b"];
    echo $a <=> $b, ' '; // 1

    // non seulement les valeurs sont comparées; les clés doivent correspondre
    $a = (object) ["a" => "b"];
    $b = (object) ["b" => "b"];
    echo $a <=> $b, ' '; // 1

    ?>

Pour les différents types, la comparaison est faite en suivant la table suivante (dans l'ordre).

Comparaison avec plusieurs types
Type de l'opérande 1 | Type de l'opérande 2 | Résultat
--- | --- | ---
null ou string | string | Convertit `null` en "", comparaison numérique ou lexicale
bool ou null | N'importe quoi | Convertit les deux côtés en bool, `false` < `true`
object | object | Les classes internes peuvent définir leur propre méthode de comparaison ; différentes classes sont incomparables ; entre objets de même classe voir Comparaison d'objet
chaîne de caractères, resource, entier ou nombre décimal | chaîne de caractères, resource, entier ou nombre décimal | Transforme les chaînes de caractères et les ressources en nombres
array | array | Le tableau avec le moins de membres est plus petit, si la clé de l'opérande 1 n'est pas trouvée dans l'opérande 2, alors les tableaux sont incomparables, sinon la comparaison se fait valeur par valeur (voir l'exemple suivant)
object | N'importe quoi | L'object est toujours plus grand
array | N'importe quoi | Le array est toujours plus grand

Exemple #2 Comparaison Booléen/null

    <?php
    // Booléen et null sont toujours comparés comme des booléens
    var_dump(1 == TRUE);  // TRUE - identique à (bool) 1 == TRUE
    var_dump(0 == FALSE); // TRUE - identique à (bool) 0 == FALSE
    var_dump(100 < TRUE); // FALSE - identique à (bool) 100 < TRUE
    var_dump(-10 < FALSE);// FALSE - identique à (bool) -10 < FALSE
    var_dump(min(-100, -10, NULL, 10, 100)); // NULL - (bool) NULL < (bool) -100 est identique à FALSE < TRUE
    ?>

Exemple #3 Transcription des comparaisons standards des tableaux

    <?php
    // Les tableaux sont comparés comme ceci avec les opérateurs standards de comparaison et l'opérateur combiné
    function standard_array_compare($op1, $op2)
    {
       if (count($op1) < count($op2)) {
          return -1; // $op1 < $op2
       } elseif (count($op1) > count($op2)) {
          return 1; // $op1 > $op2
       }
       foreach ($op1 as $key => $val) {
          if (!array_key_exists($key, $op2)) {
             return 1;
          } elseif ($val < $op2[$key]) {
             return -1;
          } elseif ($val > $op2[$key]) {
             return 1;
          }
       }
       return 0; // $op1 == $op2
    }
    ?>

Avertissement

# Comparaison de nombre à virgule flottante

À cause de la façon dont les nombres à virgule flottante sont représentés en interne, il est déconseillé de tester l'égalité entre deux nombres de type float.

Voir la documentation de float pour plus d'informations.

> Note: Il est important d'être conscient que la manipulation des types n'est pas toujours évidente lors de la comparaison de valeurs de différents types, en particulier comparant des entiers à des booléens ou des entiers à des chaîne de caractèress. Il est par conséquent généralement recommandé d'utiliser les opérateurs de comparaison `===` et `!==` au lieu de `==` et `!=` dans la plupart des cas.

### Valeurs incomparables

Tandis que les comparaisons d'identité (`===` et `!==`) peuvent être appliquées à des valeurs arbitraires, les autres opérateurs de comparaisons devraient seulement être appliqués à des valeurs comparables. Le résultat de la comparaison des valeurs incomparables est indéfini, et ne devrait pas être utilisé.

### Voir aussi

- strcasecmp()
- strcmp()
- opérateur de tableaux
- Types

### L'opérateur ternaire

Un autre opérateur conditionnel est l'opérateur ternaire ("?:").

Exemple #4 Affectation d'une valeur par défaut

    <?php
    // Exemple d'utilisation pour l'opérateur ternaire
    $action = (empty($_POST['action'])) ? 'default' : $_POST['action'];

    // La ligne ci-dessus est identique à la condition suivante :
    if (empty($_POST['action'])) {
       $action = 'default';
    } else {
       $action = $_POST['action'];
    }
    ?>

L'expression `(expr1) ? (expr2) : (expr3)` est évaluée à expr2 si expr1 est évaluée à `true`, et expr3 si expr1 est évaluée à `false`.

Il est possible d'omettre la partie centrale de l'opérateur ternaire. L'expression `expr1 ?: expr3` évalue le résultat de expr1 si expr1 vaut `true`, et expr3 sinon. expr1 n'est évalué qu'une seule fois dans ce cas.

> Note: Il est à noter que l'opérateur ternaire est une expression, et il n'est pas évalué en tant que variable, mais en tant que résultat de l'expression. Il est important de le savoir pour retourner une variable par référence. L'instruction `return $var == 42 ? $a : $b;` dans une fonction retournée par référence ne fonctionnera donc pas et une alerte est émise.

> Note:

> Il est recommandé de ne pas "empiler" les expressions ternaires. Le comportement de PHP lors de l'utilisation de plusieurs opérateurs ternaires qui ne sont pas entre parenthèses en une unique expression est non évident comparé à d'autres langages. En effet, antérieur à PHP 8.0.0, l'expression ternaire était évaluée gauche-associatif, au lieu de droite-associatif comme la plupart des autres langages de programmations. Dépendre de la gauche associativité est obsolète à partir de PHP 7.4.0. À partir de PHP 8.0.0, l'opérateur ternaire est non associatif.

> Exemple #5 Comportement de PHP

>     <?php
>     // À première vue, ce qui suit devrait retourner 'true'
>     echo (true ? 'true' : false ? 't' : 'f');

>     // cependant, l'expression ci-dessus retournera 't' antérieur à PHP 8.0.0
>     // car l'expression ternaire est gauche-associatif

>     // l'expression suivante est une version plus évidente du même code
>     echo ((true ? 'true' : false) ? 't' : 'f');

>     // ici, on peut constater que la première expression est évaluée à 'true',
>     // ce qui fait qu'elle est évaluée à (bool)true, ce qui retourne la branche
>     // 'vraie' de la seconde expression ternaire.
>     ?>

> Note:

> La combinaison de ternaire court (`?:`), cependant, est stable et se comporte de manière raisonnable. Ceci évaluera au premier argument qui évalue à une valeur non-falsy. À noter que des valeurs indéfinies émettront toujours un avertissement.

> Exemple #6 Combinaison de ternaire court

>     <?php
>     echo 0 ?: 1 ?: 2 ?: 3, PHP_EOL; //1
>     echo 0 ?: 0 ?: 2 ?: 3, PHP_EOL; //2
>     echo 0 ?: 0 ?: 0 ?: 3, PHP_EOL; //3
>     ?>

### Opérateur de fusion Null

Un autre opérateur court utile est l'opérateur "??" (ou fusion null).

Exemple #7 Assigner une valeur par défaut

    <?php
    // Exemple d'utilisation pour : Opérateur de fusion Null
    $action = $_POST['action'] ?? 'default';

    // le code ci-dessus est équivalent à cette structure if/else
    if (isset($_POST['action'])) {
        $action = $_POST['action'];
    } else {
        $action = 'default';
    }
    ?>

L'expression `(expr1) ?? (expr2)` retourne expr2 si expr1 est `null`, et expr1 dans les autres cas.

En particulier, cet opérateur n'émet pas de notice ou avertissement si la partie gauche n'existe pas, exactement comme isset(). Ceci est particulièrement utile pour les clés des tableaux.

> Note: Il est à noter que l'opérateur de fusion null est une expression, et qu'il ne s'évalue pas comme une variable, mais comme le résultat d'une expression. Il est important de le savoir pour renvoyer une variable par référence. L'expression `return $foo ?? $bar;` est un retour par référence qui ne fonctionne donc pas et émet un avertissement.

> Note:

> L'opérateur de fusion null a une précédence faible. Ceci signifie qu'en le mélangeant avec d'autres opérateurs (tels que la concaténation de chaînes ou les opérateurs arithmétiques), des parenthèses seront probablement requises.

>     <?php
>     // Émet un avertissement que $name est indéfinie.
>     print 'Mr. ' . $name ?? 'Anonymous';

>     // Affiche "Mr. Anonymous"
>     print 'Mr. ' . ($name ?? 'Anonymous');
>     ?>

> Note:

> Il est à noter que l'opérateur de fusion null permet une imbrication simple :

> Exemple #8 Imbrication de l'opérateur de fusion null

>     <?php

>     $foo = null;
>     $bar = null;
>     $baz = 1;
>     $qux = 2;

>     echo $foo ?? $bar ?? $baz ?? $qux; // affiche 1

>     ?>

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open