Files
doc-fr/language/operators.xml
2022-06-04 15:37:47 +01:00

2913 lines
83 KiB
XML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: 3d9dad29c75a70e7985ed595dfa2a836e61418da Maintainer: yannick Status: ready -->
<!-- Reviewed: no -->
<!-- CREDITS: DAnnebicque -->
<chapter xml:id="language.operators" xmlns="http://docbook.org/ns/docbook">
<title>Les opérateurs</title>
<simpara>
Un opérateur est quelque chose qui prend une ou plusieurs valeurs
(ou expressions, dans le jargon de la programmation) et qui retourne une
autre valeur (donc la construction elle-même devient une expression).
</simpara>
<para>
Les opérateurs peuvent être regroupés en fonction du nombre de valeurs
qu'ils acceptent. L'opérateur unaire n'opère que sur une seule valeur,
par exemple <literal>!</literal>
(l'<link linkend="language.operators.logical">opérateur de négation</link>)
ou <literal>++</literal>
(l'<link linkend="language.operators.increment">opérateur d'incrémentation</link>).
Le second type, les opérateurs binaires (comme le très célèbre
<link linkend="language.operators.arithmetic">opérateur mathématique</link>
<literal>+</literal> ou <literal>-</literal>) contient la plupart des opérateurs
supportés par PHP. Enfin,
l'<link linkend="language.operators.comparison.ternary">opérateur ternaire</link>,
<literal>? :</literal>, qui accepte trois valeurs (on peut aussi l'appeler l'opérateur
conditionnel).
</para>
<para>
Une liste complète des opérateurs se trouve dans la section
<link linkend="language.operators.precedence">précédence des opérateurs</link>.
Cette section explique aussi la précédence des opérateurs et l'associativité, c'est à dire
les priorités d'exécution des opérateurs.
</para>
<sect1 xml:id="language.operators.precedence">
<title>La priorité des opérateurs</title>
<para>
La priorité des opérateurs spécifie
l'ordre dans lequel les valeurs doivent être analysées.
Par exemple, dans l'expression <literal>1 + 5 * 3</literal>, le résultat est
<literal>16</literal> et non <literal>18</literal>, car la multiplication
("*") a une priorité supérieure par rapport à l'addition ("+").
Des parenthèses peuvent être utilisées pour forcer la priorité, si
nécessaire. Par exemple : <literal>(1 + 5) * 3</literal> donnera
<literal>18</literal>.
</para>
<para>
Lorsque les opérateurs ont une priorité égale, leur association
décide la façon dont les opérateurs sont groupés. Par exemple,
"-" est une association par la gauche, ainsi <literal>1 - 2 - 3</literal>
est groupé comme ceci <literal>(1 - 2) - 3</literal> et sera évalué
à <literal>-4</literal>. D'un autre côté, "=" est une association par la
droite, ainsi, <literal>$a = $b = $c</literal> est groupé comme ceci
<literal>$a = ($b = $c)</literal>.
</para>
<para>
Les opérateurs, dont la priorité est égale, qui ne sont pas associatifs,
ne peuvent pas être utilisés entre eux, par exemple,
<literal>1 &lt; 2 &gt; 1</literal> est interdit en PHP. L'expression
<literal>1 &lt;= 1 == 1</literal> par contre, est autorisée, car l'opérateur
<literal>==</literal> a une précédence inférieure que l'opérateur
<literal>&lt;=</literal>.
</para>
<para>
L'associativité à uniquement du sens pour les opérateurs binaire (et ternaire).
Les opérateurs unitaires sont soit préfixé soit suffixé ainsi cette notion
n'est pas applicable. Par exemple <literal>!!$a</literal> peut uniquement
être groupé de la manière suivante <literal>!(!$a)</literal>.
</para>
<para>
L'utilisation des parenthèses, y compris lorsqu'elles ne sont pas nécessaires,
permet de mieux lire le code en effectuant des groupements explicites
plutôt qu'imaginer la priorité des opérateurs et leurs associations.
</para>
<para>
Le tableau qui suit liste les opérateurs par ordre de priorité, avec la
priorité la plus élevée en haut. Les opérateurs sur la même ligne ont
une priorité équivalente (donc l'associativité décide du groupement).
<table>
<title>Priorité des opérateurs</title>
<tgroup cols="2">
<thead>
<row>
<entry>Associativité</entry>
<entry>Opérateurs</entry>
<entry>Information additionnelle</entry>
</row>
</thead>
<tbody>
<row>
<entry>(n/a)</entry>
<entry>
<literal>clone</literal>
<literal>new</literal>
</entry>
<entry><link linkend="language.oop5.cloning">clone</link> et <link linkend="language.oop5.basic.new">new</link></entry>
</row>
<row>
<entry>droite</entry>
<entry><literal>**</literal></entry>
<entry><link linkend="language.operators.arithmetic">arithmétique</link></entry>
</row>
<row>
<entry>(n/a)</entry>
<entry>
<literal>+</literal>
<literal>-</literal>
<literal>++</literal>
<literal>--</literal>
<literal>~</literal>
<literal>(int)</literal>
<literal>(float)</literal>
<literal>(string)</literal>
<literal>(array)</literal>
<literal>(object)</literal>
<literal>(bool)</literal>
<literal>@</literal>
</entry>
<entry>
<link linkend="language.operators.arithmetic">arithmétique</link> (unitaire <literal>+</literal> et <literal>-</literal>),
<link linkend="language.operators.increment">incrément/décrément</link>
<link linkend="language.operators.bitwise">bit à bit</link>,
<link linkend="language.types.typecasting">casting de type</link>&listendand;
<link linkend="language.operators.errorcontrol">contrôle d'erreur</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry><literal>instanceof</literal></entry>
<entry>
<link linkend="language.operators.type">type</link>
</entry>
</row>
<row>
<entry>(n/a)</entry>
<entry><literal>!</literal></entry>
<entry>
<link linkend="language.operators.logical">logique</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry>
<literal>*</literal>
<literal>/</literal>
<literal>%</literal>
</entry>
<entry>
<link linkend="language.operators.arithmetic">arithmétique</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry>
<literal>+</literal>
<literal>-</literal>
<literal>.</literal>
</entry>
<entry>
<link linkend="language.operators.arithmetic">arithmétique</link>
(binaire <literal>+</literal> et <literal>-</literal>),
<link linkend="language.operators.array">tableau</link>&listendand;
<link linkend="language.operators.string">chaîne de caractères</link>
(<literal>.</literal> antérieur à PHP 8.0.0)
</entry>
</row>
<row>
<entry>gauche</entry>
<entry>
<literal>&lt;&lt;</literal>
<literal>&gt;&gt;</literal>
</entry>
<entry>
<link linkend="language.operators.bitwise">bitwise</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry><literal>.</literal></entry>
<entry>
<link linkend="language.operators.string">string</link> (à partir de PHP 8.0.0)
</entry>
</row>
<row>
<entry>non-associatif</entry>
<entry>
<literal>&lt;</literal>
<literal>&lt;=</literal>
<literal>&gt;</literal>
<literal>&gt;=</literal>
</entry>
<entry>
<link linkend="language.operators.comparison">comparaison</link>
</entry>
</row>
<row>
<entry>non-associatif</entry>
<entry>
<literal>==</literal>
<literal>!=</literal>
<literal>===</literal>
<literal>!==</literal>
<literal>&lt;&gt;</literal>
<literal>&lt;=&gt;</literal>
</entry>
<entry>
<link linkend="language.operators.comparison">comparaison</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry><literal>&amp;</literal></entry>
<entry>
<link linkend="language.operators.bitwise">bitwise</link>&listendand;
<link linkend="language.references">références</link></entry>
</row>
<row>
<entry>gauche</entry>
<entry><literal>^</literal></entry>
<entry>
<link linkend="language.operators.bitwise">bitwise</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry><literal>|</literal></entry>
<entry>
<link linkend="language.operators.bitwise">bitwise</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry><literal>&amp;&amp;</literal></entry>
<entry>
<link linkend="language.operators.logical">logique</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry><literal>||</literal></entry>
<entry>
<link linkend="language.operators.logical">logique</link>
</entry>
</row>
<row>
<entry>droite</entry>
<entry><literal>??</literal></entry>
<entry>
<link linkend="language.operators.comparison.coalesce">coalescence nul</link>
</entry>
</row>
<row>
<entry>non-associatif</entry>
<entry><literal>? :</literal></entry>
<entry>
<link linkend="language.operators.comparison.ternary">ternaire</link>
(gauche--associatif antérieur à PHP 8.0.0)
</entry>
</row>
<row>
<entry>droite</entry>
<entry>
<literal>=</literal>
<literal>+=</literal>
<literal>-=</literal>
<literal>*=</literal>
<literal>**=</literal>
<literal>/=</literal>
<literal>.=</literal>
<literal>%=</literal>
<literal>&amp;=</literal>
<literal>|=</literal>
<literal>^=</literal>
<literal>&lt;&lt;=</literal>
<literal>&gt;&gt;=</literal>
<literal>??=</literal>
</entry>
<entry>
<link linkend="language.operators.assignment">affectation</link>
</entry>
</row>
<row>
<entry>(n/a)</entry>
<entry><literal>yield from</literal></entry>
<entry>
<link linkend="control-structures.yield.from">yield from</link>
</entry>
</row>
<row>
<entry>(n/a)</entry>
<entry><literal>yield</literal></entry>
<entry>
<link linkend="control-structures.yield">yield</link>
</entry>
</row>
<row>
<entry>(n/a)</entry>
<entry><literal>print</literal></entry>
<entry><function>print</function></entry>
</row>
<row>
<entry>gauche</entry>
<entry><literal>and</literal></entry>
<entry>
<link linkend="language.operators.logical">logique</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry><literal>xor</literal></entry>
<entry>
<link linkend="language.operators.logical">logique</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry><literal>or</literal></entry>
<entry>
<link linkend="language.operators.logical">logique</link>
</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
<example>
<title>Associativité</title>
<programlisting role="php">
<![CDATA[
<?php
$a = 3 * 3 % 5; // (3 * 3) % 5 = 4
// L'association des opérateurs ternaires diffère de C/C++
$a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2 (antérieur à PHP 8.0.0)
$a = 1;
$b = 2;
$a = $b += 3; // $a = ($b += 3) -> $a = 5, $b = 5
?>
]]>
</programlisting>
</example>
</para>
<para>
La priorité et l'association de l'opérateur ne déterminent que
la façon dont les expressions sont groupées ; ils ne spécifient
pas l'ordre de l'évaluation. PHP ne spécifie pas (de manière générale)
l'ordre dans lequel une expression est évaluée et le code qui suppose
un ordre spécifique d'évaluation ne devrait pas exister, car le
comportement peut changer entre les différentes versions de PHP
ou suivant le code environnant.
<example>
<title>Ordre d'évaluation indéfini</title>
<programlisting role="php">
<![CDATA[
<?php
$a = 1;
echo $a + $a++; // peut afficher 2 ou 3
$i = 1;
$array[$i] = $i++; // peut définir l'index 1 ou 2
?>
]]>
</programlisting>
</example>
<example>
<title>
<literal>+</literal>, <literal>-</literal> et <literal>.</literal>
ont la même priorité (antérieur à PHP 8.0.0)
</title>
<programlisting role="php">
<![CDATA[
<?php
$x = 4;
// cette ligne peut entraîner une sortie inattendue :
echo "x moins un est égal " . $x-1 . ", en tout cas j'espère\n";
// parce que c'est évalué comme la ligne suivante (antérieur à PHP 8.0.0) :
echo (("x moins un est égal " . $x) - 1) . ", en tout cas j'espère\n";
// la priorité désirée peut être renforcée en utilisant les parenthèses. :
echo "x moins un est égal " . ($x-1) . ", en tout cas j'espère\n";
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
-1, en tout cas j'espère
-1, en tout cas j'espère
x moins un est égal 3, en tout cas j'espère
]]>
</screen>
</example>
</para>
<note>
<para>
Bien que <literal>=</literal> soit prioritaire sur
la plupart des opérateurs, PHP va tout de même exécuter des
expressions comme : <literal>if (!$a = foo())</literal>.
Dans cette situation, le résultat de <literal>foo()</literal>
sera placé dans la variable <varname>$a</varname>.
</para>
</note>
<sect2 role="changelog">
&reftitle.changelog;
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry>&Version;</entry>
<entry>&Description;</entry>
</row>
</thead>
<tbody>
<row>
<entry>8.0.0</entry>
<entry>
La concaténation de chaînes de caractères (<literal>.</literal>) a désormais
une précédence moins élevée que l'addition/soustraction arithmétique
(<literal>+</literal> et <literal>-</literal>) et les shifts bit-à-bit
gauche/droite (<literal>&lt;&lt;</literal> et <literal>&gt;&gt;</literal>);
auparavant ceci avait la même précédence que <literal>+</literal> et <literal>-</literal>,
et une précédence plus élevée que <literal>&lt;&lt;</literal> et <literal>&gt;&gt;</literal>.
</entry>
</row>
<row>
<entry>8.0.0</entry>
<entry>
L'opérateur ternaire (<literal>? :</literal>) est désormais non associatif ;
auparavant il était gauche-associatif.
</entry>
</row>
<row>
<entry>7.4.0</entry>
<entry>
Dépendre de la précédence de la concaténation de chaînes de caractères
(<literal>.</literal>) relatif à l'addition/soustraction arithmétique
(<literal>+</literal> ou <literal>-</literal>) ou les shifts bit-à-bit
gauche/droite (<literal>&lt;&lt;</literal> ou <literal>&gt;&gt;</literal>),
i.e. les utiliser ensemble dans une expression sans parenthèse, est obsolète.
</entry>
</row>
<row>
<entry>7.4.0</entry>
<entry>
Dépendre de la gauche-associativité de l'opérateur ternaire (<literal>? :</literal>),
c.-à-d. l'imbrication de plusieurs opérateurs ternaires qui ne sont pas
entre parenthèse, est obsolète.
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</sect2>
</sect1>
<sect1 xml:id="language.operators.arithmetic">
<title>Les opérateurs arithmétiques</title>
<simpara>
Vous rappelez-vous des opérations élémentaires
apprises à l'école ? Les opérateurs arithmétiques fonctionnent comme elles.
</simpara>
<table>
<title>Opérations élémentaires</title>
<tgroup cols="3">
<thead>
<row>
<entry>Exemple</entry>
<entry>Nom</entry>
<entry>Résultat</entry>
</row>
</thead>
<tbody>
<row>
<entry>+$a</entry>
<entry>Identité</entry>
<entry>Conversion de <varname>$a</varname> vers <type>int</type> ou <type>float</type>,
selon le plus approprié.
</entry>
</row>
<row>
<entry>-$a</entry>
<entry>Négation</entry>
<entry>Opposé de <varname>$a</varname>.</entry>
</row>
<row>
<entry>$a + $b</entry>
<entry>Addition</entry>
<entry>Somme de <varname>$a</varname> et <varname>$b</varname>.</entry>
</row>
<row>
<entry>$a - $b</entry>
<entry>Soustraction</entry>
<entry>
Différence de <varname>$a</varname> et <varname>$b</varname>.
</entry>
</row>
<row>
<entry>$a * $b</entry>
<entry>Multiplication</entry>
<entry>Produit de <varname>$a</varname> et <varname>$b</varname>.</entry>
</row>
<row>
<entry>$a / $b</entry>
<entry>Division</entry>
<entry>
Quotient de <varname>$a</varname> et <varname>$b</varname>.
</entry>
</row>
<row>
<entry>$a % $b</entry>
<entry>Modulus</entry>
<entry>
Reste de <varname>$a</varname> divisé par <varname>$b</varname>.
</entry>
</row>
<row>
<entry>$a ** $b</entry>
<entry>Exponentiation</entry>
<entry>Résultat de l'élévation de <varname>$a</varname> à la puissance
<varname>$b</varname>.</entry>
</row>
</tbody>
</tgroup>
</table>
<simpara>
L'opérateur de division ("/") retourne une valeur à virgule flottante
sauf si les 2 opérandes sont des entiers (ou une &string; qui a été convertie
en entiers) et que leur division est exacte (i.e. a pour reste 0), auquel cas une valeur
entière sera retournée. Pour la division entière, voir
<function>intdiv</function>.
</simpara>
<simpara>
Les opérandes du modulo sont converties en <type>int</type> avant exécution.
Pour le modulo sur des nombres décimaux, voir <function>fmod</function>.
</simpara>
<para>
Le résultat de l'opération modulo <literal>%</literal> a le même signe que
le premier opérande, ansi le résultat de <literal>$a % $b</literal> aura le signe de
<varname>$a</varname>. Par exemple:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
echo (5 % 3)."\n"; // affiche 2
echo (5 % -3)."\n"; // affiche 2
echo (-5 % 3)."\n"; // affiche -2
echo (-5 % -3)."\n"; // affiche -2
?>
]]>
</programlisting>
</informalexample>
</para>
<sect2 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member><link linkend="ref.math">Les fonctions mathématiques</link></member>
</simplelist>
</para>
</sect2>
</sect1>
<sect1 xml:id="language.operators.assignment">
<title>Les opérateurs d'affectation</title>
<simpara>
L'opérateur d'affectation le plus simple est le signe "=".
Le premier réflexe est de penser que ce signe veut dire
"égal à". Ce n'est pas le cas. Il signifie que
l'opérande de gauche se voit affecter la valeur de
l'expression qui est à droite du signe égal.
</simpara>
<para>
La valeur d'une expression d'affectation est la valeur
affectée. Par exemple, la valeur de l'expression
'<literal>$a = 3</literal>' est la valeur 3. Cela permet d'utiliser
des astuces telles que :
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$a = ($b = 4) + 5;
// $a est maintenant égal à 9, et $b vaut 4.
?>
]]>
</programlisting>
</informalexample>
</para>
<para>
En plus du simple opérateur d'affectation, il existe des
"opérateurs combinés" pour tous les opérateurs
<link linkend="language.operators">arithmétiques</link>,
l'union de tableaux et pour les opérateurs sur les chaînes de caractères.
Cela permet d'utiliser la valeur d'une variable dans une expression et
d'affecter le résultat de cette expression à cette variable.
Par exemple :
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$a = 3;
$a += 5; // affecte la valeur 8 à la variable $a correspond à l'instruction '$a = $a + 5';
$b = "Bonjour ";
$b .= " tout le monde!"; // affecte la valeur "Bonjour tout le monde!" à
// la variable $b
// identique à $b = $b." tout le monde!";
?>
]]>
</programlisting>
</informalexample>
</para>
<para>
On peut noter que l'affectation copie le contenu de la variable originale
dans la nouvelle variable (affectation par valeur), ce qui fait que les
changements de valeur d'une variable ne modifieront pas la valeur de
l'autre. Cela peut se révéler important lors de la copie d'un grand tableau
durant une boucle.
</para>
<para>
Une exception au comportement d'affectation par valeur en PHP est le type
<type>object</type>, ceux-ci sont affectés par référence.
La copie d'objet doit être explicitement demandée grâce au mot-clé
<link linkend="language.oop5.cloning">clone</link>.
</para>
<sect2 xml:id="language.operators.assignment.reference">
<title>Affectation par référence</title>
<para>
L'affectation par référence est aussi supportée, au moyen de la syntaxe
"<computeroutput>$var = &amp;$othervar;</computeroutput>". L'affectation par
référence signifie que les deux variables pointent vers le même conteneur de
donnée, rien n'est copié nulle part.
</para>
<para>
<example>
<title>Affectation par référence</title>
<programlisting role="php">
<![CDATA[
<?php
$a = 3;
$b = &$a; // $b est une référence à $a
print "$a\n"; // affiche 3
print "$b\n"; // affiche 3
$a = 4; // change $a
print "$a\n"; // affiche 4
print "$b\n"; // affiche 4 aussi, car $b est une référence à $a, qui a été
// changée
?>
]]>
</programlisting>
</example>
</para>
<para>
L'opérateur <link linkend="language.oop5.basic.new">new</link>
retourne une référence automatiquement, de ce fait, assigner le résultat de
<link linkend="language.oop5.basic.new">new</link> par référence est une erreur
</para>
<para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
class C {}
$o = &new C;
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Parse error: syntax error, unexpected 'new' (T_NEW) in …
]]>
</screen>
</informalexample>
</para>
<para>
Plus d'informations sur les références et leurs utilisations possibles peuvent être
trouvées dans la section du manuel <link linkend="language.references">Les références
expliquées</link>.
</para>
</sect2>
<sect2 xml:id="language.operators.assignment.arithmetic">
<title>Les opérateurs d'affectation arithmétiques</title>
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Exemple</entry>
<entry>Equivalent</entry>
<entry>Opération</entry>
</row>
</thead>
<tbody>
<row>
<entry>$a += $b</entry>
<entry>$a = $a + $b</entry>
<entry>Addition</entry>
</row>
<row>
<entry>$a -= $b</entry>
<entry>$a = $a - $b</entry>
<entry>Soustraction</entry>
</row>
<row>
<entry>$a *= $b</entry>
<entry>$a = $a * $b</entry>
<entry>Multiplication</entry>
</row>
<row>
<entry>$a /= $b</entry>
<entry>$a = $a / $b</entry>
<entry>Division</entry>
</row>
<row>
<entry>$a %= $b</entry>
<entry>$a = $a % $b</entry>
<entry>Modulo</entry>
</row>
<row>
<entry>$a **= $b</entry>
<entry>$a = $a ** $b</entry>
<entry>Exponentiation</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</sect2>
<sect2 xml:id="language.operators.assignment.bitwise">
<title>Opérateurs d'affectation bits à bits</title>
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Exemple</entry>
<entry>Equivalent</entry>
<entry>Opération</entry>
</row>
</thead>
<tbody>
<row>
<entry>$a &amp;= $b</entry>
<entry>$a = $a &amp; $b</entry>
<entry>Opérateur And</entry>
</row>
<row>
<entry>$a |= $b</entry>
<entry>$a = $a | $b</entry>
<entry>Opérateur Or</entry>
</row>
<row>
<entry>$a ^= $b</entry>
<entry>$a = $a ^ $b</entry>
<entry>Opérateur Xor</entry>
</row>
<row>
<entry>$a &lt;&lt;= $b</entry>
<entry>$a = $a &lt;&lt; $b</entry>
<entry>Décalage à gauche</entry>
</row>
<row>
<entry>$a &gt;&gt;= $b</entry>
<entry>$a = $a &gt;&gt; $b</entry>
<entry>Décalage à droite</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</sect2>
<sect2 xml:id="language.operators.assignment.other">
<title>Autres opérateurs d'affectation</title>
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Exemple</entry>
<entry>Equivalent</entry>
<entry>Opération</entry>
</row>
</thead>
<tbody>
<row>
<entry>$a .= $b</entry>
<entry>$a = $a . $b</entry>
<entry>Concaténation d'une chaîne de caractères</entry>
</row>
<row>
<entry>$a ??= $b</entry>
<entry>$a = $a ?? $b</entry>
<entry>Opérateur de coalescence nul</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</sect2>
<sect2 role="seealso" xml:id="language.operators.assignment.see-also">
&reftitle.seealso;
<para>
<simplelist>
<member><link linkend="language.operators.arithmetic">les opérateurs arithmétiques</link></member>
<member><link linkend="language.operators.bitwise">les opérateurs bits à bits</link></member>
<member><link linkend="language.operators.comparison.coalesce">les opérateurs de coalescence nul</link></member>
</simplelist>
</para>
</sect2>
</sect1>
<sect1 xml:id="language.operators.bitwise">
<title>Opérateurs sur les bits</title>
<simpara>
Les opérateurs sur les bits vous permettent de
manipuler les bits dans un entier.
</simpara>
<table>
<title>Les opérateurs sur les bits</title>
<tgroup cols="3">
<thead>
<row>
<entry>Exemple</entry>
<entry>Nom</entry>
<entry>Résultat</entry>
</row>
</thead>
<tbody>
<row>
<entry><userinput>$a &amp; $b</userinput></entry>
<entry>And (Et)</entry>
<entry>
Les bits positionnés à 1 dans <varname>$a</varname> ET dans
<varname>$b</varname> sont positionnés à 1.
</entry>
</row>
<row>
<entry><userinput>$a | $b</userinput></entry>
<entry>Or (Ou)</entry>
<entry>
Les bits positionnés à 1 dans <varname>$a</varname> OU <varname>$b</varname>
sont positionnés à 1.
</entry>
</row>
<row>
<entry><userinput>$a ^ $b</userinput></entry>
<entry>Xor (ou exclusif)</entry>
<entry>
Les bits positionnés à 1 dans <varname>$a</varname> OU dans
<varname>$b</varname> mais pas dans les deux sont positionnés à 1.
</entry>
</row>
<row>
<entry><userinput>~ $a</userinput></entry>
<entry>Not (Non)</entry>
<entry>
Les bits qui sont positionnés à 1 dans <varname>$a</varname>
sont positionnés à 0, et vice-versa.
</entry>
</row>
<row>
<entry><userinput>$a &lt;&lt; $b</userinput></entry>
<entry>Décalage à gauche</entry>
<entry>
Décale les bits de <varname>$a</varname>, <varname>$b</varname> fois
sur la gauche (chaque décalage équivaut à une multiplication par 2).
</entry>
</row>
<row>
<entry><userinput>$a &gt;&gt; $b</userinput></entry>
<entry>Décalage à droite</entry>
<entry>
Décale les bits de <varname>$a</varname>, <varname>$b</varname> fois
sur la droite (chaque décalage équivaut à une division par 2).
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Le décalage de bits en PHP est arithmétique.
Les bits qui sont décalés hors de l'entier sont perdus.
Les décalages à gauche font apparaître des zéros à droite,
tandis que le bit de signe est décalé à gauche, ce qui signifie
que le signe de l'entier n'est pas préservé.
Les décalages à droite décalent aussi le bit de signe sur la
droite, ce qui signifie que le signe est préservé.
</para>
<para>
Utilisez des parenthèses pour vous assurer que la
<link linkend="language.operators.precedence">précédence</link>
voulue est bien appliquée. Par exemple,
<literal>$a &amp; $b == true</literal> applique d'abord
l'égalité, et ensuite le ET logique, alors que
<literal>($a &amp; $b) == true</literal> applique d'abord le
ET logique, puis l'égalité.
</para>
<para>
Si les deux opérandes pour les opérateurs <literal>&amp;</literal>,
<literal>|</literal> et <literal>^</literal> sont des chaines de caractères,
alors l'opération sera réalisée sur les valeurs ASCII des caractères et le
résultat sera une chaine de caractères. Dans tous les autres cas, les deux
opérandes seront
<link linkend="language.types.integer.casting">converties en entier</link>
et le résultat sera un entier.
</para>
<para>
Si l'opérande pour l'opérateur <literal>~</literal> operator est une chaine
de caractères, l'opération sera effectuée sur les caractères ASCII composant
la chaine et le résultat sera une chaine de caractères. Sinon l'opérande et
le résultat seront traités comme des entiers.
</para>
<para>
Les opérandes et le résultat des opérateurs <literal>&lt;&lt;</literal> et
<literal>&gt;&gt;</literal> sont traités comme des entiers.
</para>
<para>
<informalexample>
<para>
<literallayout>
Le rapport d'erreur de PHP utilise des champs de bits,
qui sont une illustration de l'extinction des bits.
Pour afficher les erreurs, sauf les notices, les
instructions du php.ini sont :
<userinput>E_ALL &amp; ~E_NOTICE</userinput>
</literallayout>
</para>
<para>
<literallayout>
Cela se comprend en comparant avec E_ALL :
<computeroutput>00000000000000000111011111111111</computeroutput>
Puis en éteignant la valeur de E_NOTICE...
<computeroutput>00000000000000000000000000001000</computeroutput>
... et en l'inversant via <literal>~</literal>:
<computeroutput>11111111111111111111111111110111</computeroutput>
Finalement, on utilise le ET logique (&amp;) pour lire les bits activés
dans les deux valeurs :
<computeroutput>00000000000000000111011111110111</computeroutput>
</literallayout>
</para>
<para>
<literallayout>
Un autre moyen d'arriver à ce résultat est d'utiliser
le OU exclusif (<literal>^</literal>), qui cherche
les bits qui ne sont activés que dans l'une ou l'autre des
valeurs, exclusivement :
<userinput>E_ALL ^ E_NOTICE</userinput>
</literallayout>
</para>
</informalexample>
</para>
<para>
<informalexample>
<para>
<literallayout>
error_reporting peut aussi être utilisé pour
illustrer l'activation de bits. Pour afficher
uniquement les erreurs et les erreurs recouvrables,
on utilise :
<userinput>E_ERROR | E_RECOVERABLE_ERROR</userinput>
</literallayout>
</para>
<para>
<literallayout>
Cette approche combine E_ERROR
<computeroutput>00000000000000000000000000000001</computeroutput>
et E_RECOVERABLE_ERROR
<computeroutput>00000000000000000001000000000000</computeroutput>
Avec l'opérateur OR (<literal>|</literal>) pour s'assurer que
les bits sont activés dans l'une ou l'autre valeur :
<computeroutput>00000000000000000001000000000001</computeroutput>
</literallayout>
</para>
</informalexample>
</para>
<para>
<example>
<title>Opérations sur les bits et les entiers</title>
<programlisting role="php">
<![CDATA[
<?php
/*
* Ignorez cette partie,
* c'est juste du formatage pour clarifier les résultats
*/
$format = '(%1$2d = %1$04b) = (%2$2d = %2$04b)'
. ' %3$s (%4$2d = %4$04b)' . "\n";
echo <<<EOH
--------- --------- -- ---------
résultat valeur test
--------- --------- -- ---------
EOH;
/*
* Voici les exemples
*/
$values = array(0, 1, 2, 4, 8);
$test = 1 + 4;
echo "\n Bitwise AND \n";
foreach ($values as $value) {
$result = $value & $test;
printf($format, $result, $value, '&', $test);
}
echo "\n Bitwise Inclusive OR \n";
foreach ($values as $value) {
$result = $value | $test;
printf($format, $result, $value, '|', $test);
}
echo "\n Bitwise Exclusive OR (XOR) \n";
foreach ($values as $value) {
$result = $value ^ $test;
printf($format, $result, $value, '^', $test);
}
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
--------- --------- -- ---------
résultat valeur test
--------- --------- -- ---------
Bitwise AND
( 0 = 0000) = ( 0 = 0000) & ( 5 = 0101)
( 1 = 0001) = ( 1 = 0001) & ( 5 = 0101)
( 0 = 0000) = ( 2 = 0010) & ( 5 = 0101)
( 4 = 0100) = ( 4 = 0100) & ( 5 = 0101)
( 0 = 0000) = ( 8 = 1000) & ( 5 = 0101)
Bitwise Inclusive OR
( 5 = 0101) = ( 0 = 0000) | ( 5 = 0101)
( 5 = 0101) = ( 1 = 0001) | ( 5 = 0101)
( 7 = 0111) = ( 2 = 0010) | ( 5 = 0101)
( 5 = 0101) = ( 4 = 0100) | ( 5 = 0101)
(13 = 1101) = ( 8 = 1000) | ( 5 = 0101)
Bitwise Exclusive OR (XOR)
( 5 = 0101) = ( 0 = 0000) ^ ( 5 = 0101)
( 4 = 0100) = ( 1 = 0001) ^ ( 5 = 0101)
( 7 = 0111) = ( 2 = 0010) ^ ( 5 = 0101)
( 1 = 0001) = ( 4 = 0100) ^ ( 5 = 0101)
(13 = 1101) = ( 8 = 1000) ^ ( 5 = 0101)
]]>
</screen>
</example>
</para>
<para>
<example>
<title>Opération sur les bits et les chaînes</title>
<programlisting role="php">
<![CDATA[
<?php
echo 12 ^ 9; // Affiche '5'
echo "12" ^ "9"; // Affiche le caractère d'effacement (ascii 8)
// ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8
echo "hallo" ^ "hello"; // Affiche les valeurs ASCII #0 #4 #0 #0 #0
// 'a' ^ 'e' = #4
echo 2 ^ "3"; // Affiche 1
// 2 ^ ((int)"3") == 1
echo "2" ^ 3; // Affiche 1
// ((int)"2") ^ 3 == 1
?>
]]>
</programlisting>
</example>
</para>
<para>
<example>
<title>Décalage de bits sur les entiers</title>
<programlisting role="php">
<![CDATA[
<?php
/*
* Voici quelques exemples
*/
echo "\n--- Décalages à droite sur des entiers positifs ---\n";
$val = 4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'copie du bit de signe maintenant à gauche');
$val = 4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places);
$val = 4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'des bits sont sortis par la droite');
$val = 4;
$places = 4;
$res = $val >> $places;
p($res, $val, '>>', $places, 'même résultat que ci-dessus : pas de décalage au dela de 0');
echo "\n--- Décalages à droite sur des entiers négatifs ---\n";
$val = -4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'copie du bit de signe maintenant à gauche');
$val = -4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places, 'des bits sont sortis par la droite');
$val = -4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'même résultat que ci-dessus : pas de décalage au dela de -1');
echo "\n--- Décalages à gauche sur des entiers positifs ---\n";
$val = 4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'complément de zéros à droite');
$val = 4;
$places = (PHP_INT_SIZE * 8) - 4;
$res = $val << $places;
p($res, $val, '<<', $places);
$val = 4;
$places = (PHP_INT_SIZE * 8) - 3;
$res = $val << $places;
p($res, $val, '<<', $places, 'le bit de signe est sorti');
$val = 4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val << $places;
p($res, $val, '<<', $places, 'des bits sont sortis à gauche');
echo "\n--- Décalages à gauche sur des entiers négatifs ---\n";
$val = -4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'complément de zéros à droite');
$val = -4;
$places = (PHP_INT_SIZE * 8) - 3;
$res = $val << $places;
p($res, $val, '<<', $places);
$val = -4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val << $places;
p($res, $val, '<<', $places, 'des bits sont sortis à gauche, y compris le bit de signe');
/*
* Ignorez cette section
* Elle contient du code pour le formatage de cet exemple
*/
function p($res, $val, $op, $places, $note = '') {
$format = '%0' . (PHP_INT_SIZE * 8) . "b\n";
printf("Expression : %d = %d %s %d\n", $res, $val, $op, $places);
echo " Décimal :\n";
printf(" val=%d\n", $val);
printf(" res=%d\n", $res);
echo " Binaire :\n";
printf(' val=' . $format, $val);
printf(' res=' . $format, $res);
if ($note) {
echo " Note : $note\n";
}
echo "\n";
}
?>
]]>
</programlisting>
&example.outputs.32bit;
<screen>
<![CDATA[
--- Décalages à droite sur des entiers positifs ---
Expression : 2 = 4 >> 1
Décimal :
val=4
res=2
Binaire :
val=00000000000000000000000000000100
res=00000000000000000000000000000010
Note : copie du bit de signe maintenant à gauche
Expression : 1 = 4 >> 2
Décimal :
val=4
res=1
Binaire :
val=00000000000000000000000000000100
res=00000000000000000000000000000001
Expression : 0 = 4 >> 3
Décimal :
val=4
res=0
Binaire :
val=00000000000000000000000000000100
res=00000000000000000000000000000000
Note : des bits sont sortis par la droite
Expression : 0 = 4 >> 4
Décimal :
val=4
res=0
Binaire :
val=00000000000000000000000000000100
res=00000000000000000000000000000000
Note : même résultat que ci-dessus : pas de décalage au dela de 0
--- Décalages à droite sur des entiers négatifs ---
Expression : -2 = -4 >> 1
Décimal :
val=-4
res=-2
Binaire :
val=11111111111111111111111111111100
res=11111111111111111111111111111110
Note : copie du bit de signe à gauche
Expression : -1 = -4 >> 2
Décimal :
val=-4
res=-1
Binaire :
val=11111111111111111111111111111100
res=11111111111111111111111111111111
Note : des bits sont sortis par la droite
Expression : -1 = -4 >> 3
Décimal :
val=-4
res=-1
Binaire :
val=11111111111111111111111111111100
res=11111111111111111111111111111111
Note : même résultat que ci-dessus : pas de décalage au dela de -1
--- Décalages à gauche sur des entiers positifs ---
Expression : 8 = 4 << 1
Décimal :
val=4
res=8
Binaire :
val=00000000000000000000000000000100
res=00000000000000000000000000001000
Note : complément de zéros à droite
Expression : 1073741824 = 4 << 28
Décimal :
val=4
res=1073741824
Binaire :
val=00000000000000000000000000000100
res=01000000000000000000000000000000
Expression : -2147483648 = 4 << 29
Décimal :
val=4
res=-2147483648
Binaire :
val=00000000000000000000000000000100
res=10000000000000000000000000000000
Note : le bit de signe est sorti
Expression : 0 = 4 << 30
Décimal :
val=4
res=0
Binaire :
val=00000000000000000000000000000100
res=00000000000000000000000000000000
Note : des bits sont sortis à gauche
--- Décalages à gauche sur des entiers négatifs ---
Expression : -8 = -4 << 1
Décimal :
val=-4
res=-8
Binaire :
val=11111111111111111111111111111100
res=11111111111111111111111111111000
Note : complément de zéros à droite
Expression : -2147483648 = -4 << 29
Décimal :
val=-4
res=-2147483648
Binaire :
val=11111111111111111111111111111100
res=10000000000000000000000000000000
Expression : 0 = -4 << 30
Décimal :
val=-4
res=0
Binaire :
val=11111111111111111111111111111100
res=00000000000000000000000000000000
Note : des bits sont sortis à gauche, y compris le bit de signe
]]>
</screen>
&example.outputs.64bit;
<screen>
<![CDATA[
--- Décalages à droite sur des entiers positifs ---
Expression : 2 = 4 >> 1
Décimal :
val=4
res=2
Binaire :
val=0000000000000000000000000000000000000000000000000000000000000100
res=0000000000000000000000000000000000000000000000000000000000000010
Note : copie du bit de signe maintenant à gauche
Expression : 1 = 4 >> 2
Décimal :
val=4
res=1
Binaire :
val=0000000000000000000000000000000000000000000000000000000000000100
res=0000000000000000000000000000000000000000000000000000000000000001
Expression : 0 = 4 >> 3
Décimal :
val=4
res=0
Binaire :
val=0000000000000000000000000000000000000000000000000000000000000100
res=0000000000000000000000000000000000000000000000000000000000000000
Note : des bits sont sortis par la droite
Expression : 0 = 4 >> 4
Décimal :
val=4
res=0
Binaire :
val=0000000000000000000000000000000000000000000000000000000000000100
res=0000000000000000000000000000000000000000000000000000000000000000
Note : même résultat que ci-dessus : pas de décalage au dela de 0
--- Décalages à droite sur des entiers négatifs ---
Expression : -2 = -4 >> 1
Décimal :
val=-4
res=-2
Binaire :
val=1111111111111111111111111111111111111111111111111111111111111100
res=1111111111111111111111111111111111111111111111111111111111111110
Note : copie du bit de signe maintenant à gauche
Expression : -1 = -4 >> 2
Décimal :
val=-4
res=-1
Binaire :
val=1111111111111111111111111111111111111111111111111111111111111100
res=1111111111111111111111111111111111111111111111111111111111111111
Note : des bits sont sortis par la droite
Expression : -1 = -4 >> 3
Décimal :
val=-4
res=-1
Binaire :
val=1111111111111111111111111111111111111111111111111111111111111100
res=1111111111111111111111111111111111111111111111111111111111111111
Note : même résultat que ci-dessus : pas de décalage au dela de -1
--- Décalage à gauche sur les entiers négatifs ---
Expression : 8 = 4 << 1
Décimal :
val=4
res=8
Binaire :
val=0000000000000000000000000000000000000000000000000000000000000100
res=0000000000000000000000000000000000000000000000000000000000001000
Note : complément de zéros à droite
Expression : 4611686018427387904 = 4 << 60
Décimal :
val=4
res=4611686018427387904
Binaire :
val=0000000000000000000000000000000000000000000000000000000000000100
res=0100000000000000000000000000000000000000000000000000000000000000
Expression : -9223372036854775808 = 4 << 61
Décimal :
val=4
res=-9223372036854775808
Binaire :
val=0000000000000000000000000000000000000000000000000000000000000100
res=1000000000000000000000000000000000000000000000000000000000000000
Note : le bit de signe est sorti
Expression : 0 = 4 << 62
Décimal :
val=4
res=0
Binaire :
val=0000000000000000000000000000000000000000000000000000000000000100
res=0000000000000000000000000000000000000000000000000000000000000000
Note : des bits sont sortis à gauche
--- Décalage à gauche sur les entiers négatifs ---
Expression : -8 = -4 << 1
Décimal :
val=-4
res=-8
Binaire :
val=1111111111111111111111111111111111111111111111111111111111111100
res=1111111111111111111111111111111111111111111111111111111111111000
Note : complément de zéros à droite
Expression : -9223372036854775808 = -4 << 61
Décimal :
val=-4
res=-9223372036854775808
Binaire :
val=1111111111111111111111111111111111111111111111111111111111111100
res=1000000000000000000000000000000000000000000000000000000000000000
Expression : 0 = -4 << 62
Décimal :
val=-4
res=0
Binaire :
val=1111111111111111111111111111111111111111111111111111111111111100
res=0000000000000000000000000000000000000000000000000000000000000000
Note : des bits sont sortis à gauche, y compris le bit de signe
]]>
</screen>
</example>
</para>
<warning>
<para>
Utilisez les fonctions de l'extension <link linkend="book.gmp">gmp</link>
pour les manipulations sur les bits, lorsque les entiers dépassent
<literal>PHP_INT_MAX</literal>.
</para>
</warning>
<sect2 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member><function>pack</function></member>
<member><function>unpack</function></member>
<member><function>gmp_and</function></member>
<member><function>gmp_or</function></member>
<member><function>gmp_xor</function></member>
<member><function>gmp_testbit</function></member>
<member><function>gmp_clrbit</function></member>
</simplelist>
</para>
</sect2>
</sect1>
<sect1 xml:id="language.operators.comparison">
<title>Opérateurs de comparaison</title>
<simpara>
Les opérateurs de comparaison, comme leur nom l'indique,
vous permettent de comparer deux valeurs. Vous devriez également être
intéressés par les
<link linkend="types.comparisons">tables de comparaisons de types</link>,
car ils montrent des exemples de beaucoup de types de comparaisons.
</simpara>
<table>
<title>Opérateurs de comparaison</title>
<tgroup cols="3">
<thead>
<row>
<entry>Exemple</entry>
<entry>Nom</entry>
<entry>Résultat</entry>
</row>
</thead>
<tbody>
<row>
<entry>$a == $b</entry>
<entry>Égal</entry>
<entry>&true; si <varname>$a</varname> est égal à
<varname>$b</varname> après le transtypage.</entry>
</row>
<row>
<entry>$a === $b</entry>
<entry>Identique</entry>
<entry>
&true; si <varname>$a</varname> est égal à <varname>$b</varname> et
qu'ils sont de même type.
</entry>
</row>
<row>
<entry>$a != $b</entry>
<entry>Différent</entry>
<entry>&true; si <varname>$a</varname> est différent de
<varname>$b</varname> après le transtypage.</entry>
</row>
<row>
<entry>$a &lt;&gt; $b</entry>
<entry>Différent</entry>
<entry>&true; si <varname>$a</varname> est différent de
<varname>$b</varname> après le transtypage.</entry>
</row>
<row>
<entry>$a !== $b</entry>
<entry>Différent</entry>
<entry>
&true; si <varname>$a</varname> est différent de <varname>$b</varname>
ou bien s'ils ne sont pas du même type.
</entry>
</row>
<row>
<entry>$a &lt; $b</entry>
<entry>Plus petit que</entry>
<entry>&true; si <varname>$a</varname> est strictement plus petit que
<varname>$b</varname>.</entry>
</row>
<row>
<entry>$a &gt; $b</entry>
<entry>Plus grand</entry>
<entry>&true; si <varname>$a</varname> est strictement plus grand que
<varname>$b</varname>.</entry>
</row>
<row>
<entry>$a &lt;= $b</entry>
<entry>Inférieur ou égal</entry>
<entry>&true; si <varname>$a</varname> est plus petit ou égal à
<varname>$b</varname>.</entry>
</row>
<row>
<entry>$a &gt;= $b</entry>
<entry>Supérieur ou égal</entry>
<entry>&true; si <varname>$a</varname> est plus grand ou égal à
<varname>$b</varname>.</entry>
</row>
<row>
<entry>$a &lt;=&gt; $b</entry>
<entry>Combiné</entry>
<entry>
Un &integer; inférieur, égal ou supérieur à zéro lorsque
<varname>$a</varname> est inférieur, égal, ou supérieur à
<varname>$b</varname> respectivement.
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Si les deux opérandes sont des
<link linkend="language.types.numeric-strings">chaînes numériques</link>,
ou si un opérande est un nombre et l'autre est une
<link linkend="language.types.numeric-strings">chaîne numérique</link>,
alors la comparaison sera effectuée numériquement.
Ces règles s'appliquent également à l'instruction
<link linkend="control-structures.switch">switch</link>.
La conversion de type n'intervient pas lorsque la comparaison est
<literal>===</literal> ou <literal>!==</literal>
vu que ceci engendre aussi bien une comparaison de type que de valeur.
</para>
<warning>
<para>
Antérieur à PHP 8.0.0, si une <type>string</type> est comparé à un nombre
ou à une chaîne numérique alors la <type>string</type> sera convertie en un
nombre avant d'effectuer la comparaison. Ceci peut mener à des résultats
surprenant comme il peut être vu avec l'exemple suivant :
<informalexample>
<programlisting role="php">
<![CDATA[
<?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;
}
?>
]]>
</programlisting>
&example.outputs.7;
<screen>
<![CDATA[
bool(true)
bool(true)
bool(true)
bool(true)
0
]]>
</screen>
&example.outputs.8;
<screen>
<![CDATA[
bool(false)
bool(true)
bool(true)
bool(true)
a
]]>
</screen>
</informalexample>
</para>
</warning>
<para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
// Entiers
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// Nombre flottants
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// Chaines 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
?>
]]>
</programlisting>
</informalexample>
</para>
<para>
Pour les différents types, la comparaison est faite en suivant
la table suivante (dans l'ordre).
</para>
<table xml:id="language.operators.comparison.types">
<title>Comparaison avec plusieurs types</title>
<tgroup cols="3">
<thead>
<row>
<entry>Type de l'opérande 1</entry>
<entry>Type de l'opérande 2</entry>
<entry>Résultat</entry>
</row>
</thead>
<tbody>
<row>
<entry><type>null</type> ou <type>string</type></entry>
<entry><type>string</type></entry>
<entry>Convertit &null; en "", comparaison numérique ou lexicale</entry>
</row>
<row>
<entry><type>bool</type> ou <type>null</type></entry>
<entry>N'importe quoi</entry>
<entry>Convertit en <type>bool</type>, &false; &lt; &true;</entry>
</row>
<row>
<entry><type>object</type></entry>
<entry><type>object</type></entry>
<entry>Les classes internes peuvent définir leur propre méthode de
comparaison; différentes classes sont incomparables; entre objets
de même classe voir <link
linkend="language.oop5.object-comparison">Comparaison d'objet</link></entry>
</row>
<row>
<entry>
&string;, &resource;, &integer; ou &float;
</entry>
<entry>
&string;, &resource;, &integer; ou &float;
</entry>
<entry>
Transforme les chaînes de caractères et les ressources en nombres
</entry>
</row>
<row>
<entry><type>array</type></entry>
<entry><type>array</type></entry>
<entry>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)
</entry>
</row>
<row>
<entry><type>object</type></entry>
<entry>N'importe quoi</entry>
<entry>L'<type>objet</type> est toujours plus grand</entry>
</row>
<row>
<entry><type>array</type></entry>
<entry>N'importe quoi</entry>
<entry>Le <type>tableau</type> est toujours plus grand</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
<example>
<title>Comparaison Booléen/null</title>
<programlisting role="php">
<![CDATA[
<?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
?>
]]>
</programlisting>
</example>
</para>
<para>
<example>
<title>Transcription des comparaisons standards des tableaux</title>
<programlisting role="php">
<![CDATA[
<?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
}
?>
]]>
</programlisting>
</example>
</para>
<warning>
<title>Comparaison de nombre à virgule flottante</title>
<para>
A cause de la façon dont les nombres à virgule flottante sont représentés
en interne, vous ne devriez pas tester l'égalité entre deux nombres
de type <type>float</type>.
</para>
<para>
Voyez la documentation de <type>float</type> pour plus d'informations.
</para>
</warning>
<note>
<simpara>
Soyer 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 &integer;s à des &boolean;s ou des
&integer;s à des &string;s. Il est par conséquent généralement recommandé d'utiliser les
opérateurs de comparaison <literal>===</literal> et <literal>!==</literal> au lieu de
<literal>==</literal> et <literal>!=</literal> dans la plupart des cas.
</simpara>
</note>
<sect2 xml:id="language.operators.comparison.incomparable">
<title>Valeurs incomparables</title>
<simpara>
Tandis que les comparaisons d'identité (<literal>===</literal> et <literal>!==</literal>)
peuvent être appliqué à des valeurs arbitraires, les autres opérateurs de
comparaisons devrait seulement être appliqué à des valeurs comparables.
Le résultat de comparer des valeurs incomparables est indéfinie,
et ne devrait pas être dépendu.
</simpara>
</sect2>
<sect2 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member><function>strcasecmp</function></member>
<member><function>strcmp</function></member>
<member><link linkend="language.operators.array">opérateur de tableaux</link></member>
<member><link linkend="language.types">Types</link></member>
</simplelist>
</para>
</sect2>
<sect2 xml:id="language.operators.comparison.ternary">
<title>L'opérateur ternaire</title>
<para>
Un autre opérateur conditionnel est l'opérateur
ternaire ("?:").
<example>
<title>Affectation d'une valeur par défaut</title>
<programlisting role="php">
<![CDATA[
<?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'];
}
?>
]]>
</programlisting>
</example>
L'expression <literal>(expr1) ? (expr2) : (expr3)</literal>
est évaluée à <replaceable>expr2</replaceable> si
<replaceable>expr1</replaceable> est évaluée à &true;, et
<replaceable>expr3</replaceable> si
<replaceable>expr1</replaceable> est évaluée à &false;.
</para>
<para>
Il est possible d'omettre la partie centrale de l'opérateur ternaire.
L'expression <literal>expr1 ?: expr3</literal> évalue le résultat de
<replaceable>expr1</replaceable> si <replaceable>expr1</replaceable>
vaut &true;, et <replaceable>expr3</replaceable> sinon.
<replaceable>expr1</replaceable> n'est évalué qu'une seule fois dans ce cas.
</para>
<note>
<simpara>
Notez 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 si vous voulez retourner une variable
par référence. L'instruction
<literal>return $var == 42 ? $a : $b;</literal>
dans une fonction retournée par référence ne fonctionnera donc pas et une
alerte est émise.
</simpara>
</note>
<note>
<para>
Il est recommandé de ne pas "empiler" les expressions ternaires.
Le comportement de PHP lors de l'utilisation de plusieurs opérateurs
ternaire qui ne sont pas entre parenthèse en une unique expression est
non évident comparé à d'autres langages.
En effet antérieur à PHP 8.0.0, l'expression ternaire était évalué
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.
<example>
<title>Comportement de PHP</title>
<programlisting role="php">
<![CDATA[
<?php
// A 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.
?>
]]>
</programlisting>
</example>
</para>
</note>
<note>
<para>
La combinaison de ternaire court (<literal>?:</literal>), cependant, est stable et se comporte de manière résonable.
Ceci évaluera au premier argument qui évalue à une valeur non-falsy.
À noter que des valeurs indéfinies émettront toujours un avertissement.
<example>
<title>Combinaison de ternaire court</title>
<programlisting role="php">
<![CDATA[
<?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
?>
]]>
</programlisting>
</example>
</para>
</note>
</sect2>
<sect2 xml:id="language.operators.comparison.coalesce">
<title>Opérateur de fusion Null</title>
<para>
Un autre opérateur court utile est l'opérateur "??" (ou fusion null).
<example>
<title>Assigner une valeur par défaut</title>
<programlisting role="php">
<![CDATA[
<?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';
}
?>
]]>
</programlisting>
</example>
L'expression <literal>(expr1) ?? (expr2)</literal> retourne
<replaceable>expr2</replaceable> si <replaceable>expr1</replaceable> est
&null;, et <replaceable>expr1</replaceable> dans les autres cas.
</para>
<para>
En particulier, cet opérateur n'émet pas de notice ou avertissement si
la partie gauche n'existe pas, exactement comme <function>isset</function>.
Ceci est particulièrement utile pour les clés des tableaux.
</para>
<note>
<simpara>
Veuillez noter que l'opérateur null de fusion 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 si vous souhaitez renvoyer une variable
par référence.
L'expression <literal>return $foo ?? $bar;</literal> est un retour par
référence qui ne fonctionne donc pas et émet un avertissement.
</simpara>
</note>
<note>
<para>
L'opérateur de fusion null à une précédence faible. Ceci signifie que le mélanger
avec d'autres opérateurs (tel que la concaténation de chaînes ou les opérateurs
arithmétiques) des parenthèses seront requis.
</para>
<programlisting role="php">
<![CDATA[
<?php
// Émet un avertissement que $name est indéfinie.
print 'Mr. ' . $name ?? 'Anonymous';
// Prints "Mr. Anonymous"
print 'Mr. ' . ($name ?? 'Anonymous');
?>
]]>
</programlisting>
</note>
<note>
<para>
Veuillez noter que l'opérateur de fusion null permet une imbrication simple:
<example>
<title>Imbrication de l'opération de fusion null</title>
<programlisting role="php">
<![CDATA[
<?php
$foo = null;
$bar = null;
$baz = 1;
$qux = 2;
echo $foo ?? $bar ?? $baz ?? $qux; // sortie 1
?>
]]>
</programlisting>
</example>
</para>
</note>
</sect2>
</sect1>
<sect1 xml:id="language.operators.errorcontrol">
<title>Opérateur de contrôle d'erreur</title>
<simpara>
PHP supporte un opérateur de contrôle d'erreur : l'arobase (<literal>@</literal>).
Lorsque cet opérateur est ajouté en préfixe d'une
expression PHP, les diagnostics d'erreurs qui peuvent être
générés par cette expression seront ignorés.
</simpara>
<para>
Si un gestionnaire d'erreur personnalisé est défini avec
<function>set_error_handler</function>, il sera quand même appelé même si
le diagnostic a été ignorée.
</para>
<warning>
<para>
Antérieur à PHP 8.0.0, le <function>error_reporting</function> appelée dans le gestionnaire d'erreur
personnalisé retournait toujours <literal>0</literal> si le l'erreur a été ignorée avec l'opérateur <literal>@</literal>.
À partir de 8.0.0, il retourne la valeur <literal>E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_PARSE</literal>.
</para>
</warning>
<simpara>
Tous les messages d'erreur générés par l'expression sont disponibles
dans l'élément <literal>"message"</literal> du tableau retourné par
la fonction <function>error_get_last</function>. Le résultat de la fonction
changera à chaque erreur, aussi, il convient de le vérifier souvent.
</simpara>
<para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
/* Erreur intentionnelle (le fichier n'existe pas): */
$mon_fichier = @file ('non_persistent_file') or
die ("Impossible d'ouvrir le fichier : L'erreur est : '" . error_get_last()['message'] . "'");
// Cela fonctionne avec n'importe quelle expression, pas seulement les fonctions
$value = @$cache[$key];
// la ligne ci-dessus n'affichera pas d'alerte si la clé $key du tableau n'existe pas
?>
]]>
</programlisting>
</informalexample>
</para>
<note>
<simpara>
L'opérateur <literal>@</literal> ne fonctionne qu'avec les
<link linkend="language.expressions">expressions</link>.
La règle générale est : s'il est possible de prendre la valeur de quelque
chose alors on peut préfixer l'opérateur <literal>@</literal> à celui-ci.
Par exemple, il peut être préfixé devant les variables, appels de fonctions,
certains appels aux constructions de langages (e.g.
<function>include</function>), etc.
Il ne peut pas être préfixé devant les définitions de fonctions ou de classes
ou structures conditionnelles telles que <literal>if</literal> et &foreach;, etc.
</simpara>
</note>
<warning>
<para>
Antérieur à PHP 8.0.0, il était possible pour l'opérateur
<literal>@</literal> de désactiver les erreurs critiques qui terminait
l'exécution du script.
Par exemple, préfixer <literal>@</literal> à un appel d'une fonction qui
n'existe pas, en étant indisponible ou mal orthographiée, causait le script
à se terminer sans aucune indication pourquoi.
</para>
</warning>
<sect2 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member><function>error_reporting</function></member>
<member><link linkend="ref.errorfunc">Gestion d'Erreur et fonction de Logging</link></member>
</simplelist>
</para>
</sect2>
</sect1>
<sect1 xml:id="language.operators.execution">
<title>Opérateur d'exécution</title>
<para>
PHP supporte un opérateur d'exécution : guillemets obliques
("``"). Notez bien qu'il ne s'agit pas de guillemets simples. PHP
essaie d'exécuter le contenu de ces guillemets obliques comme une commande
shell. Le résultat sera retourné (c'est-à-dire : il ne sera pas simplement
envoyé à la sortie standard, il peut être affecté à une variable).
Utiliser les guillemets obliques revient à utiliser la fonction
<function>shell_exec</function>.
<example>
<title>Opérateur d'exécution</title>
<programlisting role="php">
<![CDATA[
<?php
$output = `ls -al`;
echo "<pre>$output</pre>";
?>
]]>
</programlisting>
</example>
</para>
<note>
<para>
Cet opérateur est désactivé lorsque la fonction
<function>shell_exec</function> est désactivée.
</para>
</note>
<note>
<para>
Contrairement à d'autres langages, les guillemets obliques
n'ont pas de signification spéciale dans une chaîne entourée
de guillemets doubles.
</para>
</note>
<sect2 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member><link linkend="ref.exec">Les fonctions d'exécution système</link></member>
<member><function>popen</function></member>
<member><function>proc_open</function></member>
<member><link linkend="features.commandline">Utiliser PHP depuis la ligne de commande</link></member>
</simplelist>
</para>
</sect2>
</sect1>
<sect1 xml:id="language.operators.increment">
<title>Opérateurs d'incrémentation et décrémentation</title>
<para>
PHP supporte les opérateurs de pre- et post-incrémentation et
décrémentation, comme en langage C.
</para>
<note>
<simpara>
Les opérateurs d'incrémentation/décrémentation n'affectent que les
nombres et les chaînes de caractères.
Les tableaux, objets, booléen et ressources ne sont pas affectées.
La décrémentation des valeurs &null; n'a également aucun effet,
mais leur incrémentation donnera comme résultat <literal>1</literal>.
</simpara>
</note>
<table>
<title>Opérateurs d'incrémentation et décrémentation</title>
<tgroup cols="3">
<thead>
<row>
<entry>Exemple</entry>
<entry>Nom</entry>
<entry>Résultat</entry>
</row>
</thead>
<tbody>
<row>
<entry>++$a</entry>
<entry>Pre-incrémente</entry>
<entry>
Incrémente <varname>$a</varname> de 1, puis retourne
<varname>$a</varname>.
</entry>
</row>
<row>
<entry>$a++</entry>
<entry>Post-incrémente</entry>
<entry>Retourne <varname>$a</varname>, puis incrémente <varname>$a</varname> de 1.</entry>
</row>
<row>
<entry>--$a</entry>
<entry>Pré-décrémente</entry>
<entry>
Décrémente <varname>$a</varname> de 1, puis retourne
<varname>$a</varname>.
</entry>
</row>
<row>
<entry>$a--</entry>
<entry>Post-décrémente</entry>
<entry>
Retourne <varname>$a</varname>, puis décrémente
<varname>$a</varname> de 1.
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Voici un exemple simple :
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
echo '<h3>Post-incrémentation</h3>';
$a = 5;
echo "Devrait valoir 5: " . $a++ . "<br />\n";
echo "Devrait valoir 6: " . $a . "<br />\n";
echo '<h3>Pre-incrémentation</h3>';
$a = 5;
echo "Devrait valoir 6: " . ++$a . "<br />\n";
echo "Devrait valoir 6: " . $a . "<br />\n";
echo '<h3>Post-décrémentation</h3>';
$a = 5;
echo "Devrait valoir 5: " . $a-- . "<br />\n";
echo "Devrait valoir 4: " . $a . "<br />\n";
echo '<h3>Pre-décrémentation</h3>';
$a = 5;
echo "Devrait valoir 4: " . --$a . "<br />\n";
echo "Devrait valoir 4: " . $a . "<br />\n";
?>
]]>
</programlisting>
</informalexample>
</para>
<para>
PHP suit les conventions de Perl pour la gestion des opérateurs
arithmétiques sur les variables de caractères et non pas celle du C.
Par exemple, en PHP et en Perl, <literal>$a = 'Z'; $a++;</literal>
transforme <literal>$a</literal> en <literal>'AA'</literal>,
alors qu'en C, <literal>a = 'Z'; a++;</literal> transforme
<literal>a</literal> en <literal>'['</literal> (la valeur ASCII de
<literal>'Z'</literal> est 90, la valeur ASCII de <literal>'['</literal>
est 91). Notez que les variables de caractères peuvent être incrémentés,
mais pas décrémentées, mais aussi que seuls les caractères ASCII pleins
et les chiffres (a-z, A-Z et 0-9) sont supportés.
L'incrémentation/décrémentation d'autres variables de caractères n'a
aucun effet, la chaîne originale n'est pas modifiée.
<example>
<title>Opérations arithmétiques sur un caractère</title>
<programlisting role="php">
<![CDATA[
<?php
echo '== Alphabets ==' . PHP_EOL;
$s = 'W';
for ($n=0; $n<6; $n++) {
echo ++$s . PHP_EOL;
}
// Les caractères digitaux réagissent différemment
echo '== Caractères digitaux ==' . PHP_EOL;
$d = 'A8';
for ($n=0; $n<6; $n++) {
echo ++$d . PHP_EOL;
}
$d = 'A08';
for ($n=0; $n<6; $n++) {
echo ++$d . PHP_EOL;
}
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
== Alphabets ==
X
Y
Z
AA
AB
AC
== Caractères digitaux ==
A9
B0
B1
B2
B3
B4
A09
A10
A11
A12
A13
A14
]]>
</screen>
</example>
</para>
<para>
L'incrémentation ou la décrémentation d'un booléen n'a aucun effet.
</para>
</sect1>
<sect1 xml:id="language.operators.logical">
<title>Les opérateurs logiques</title>
<table>
<title>Les opérateurs logiques</title>
<tgroup cols="3">
<thead>
<row>
<entry>Exemple</entry>
<entry>Nom</entry>
<entry>Résultat</entry>
</row>
</thead>
<tbody>
<row>
<entry>$a and $b</entry>
<entry>And (Et)</entry>
<entry>&true; si <varname>$a</varname> ET <varname>$b</varname> valent &true;.</entry>
</row>
<row>
<entry>$a or $b</entry>
<entry>Or (Ou)</entry>
<entry>&true; si <varname>$a</varname> OU <varname>$b</varname> valent &true;.</entry>
</row>
<row>
<entry>$a xor $b</entry>
<entry>XOR</entry>
<entry>
&true; si <varname>$a</varname> OU <varname>$b</varname> est &true;,
mais pas les deux en même temps.
</entry>
</row>
<row>
<entry>! $a</entry>
<entry>Not (Non)</entry>
<entry>&true; si <varname>$a</varname> n'est pas &true;.</entry>
</row>
<row>
<entry>$a &amp;&amp; $b</entry>
<entry>And (Et)</entry>
<entry>&true; si <varname>$a</varname> ET <varname>$b</varname> sont &true;.</entry>
</row>
<row>
<entry>$a || $b</entry>
<entry>Or (Ou)</entry>
<entry>&true; si <varname>$a</varname> OU <varname>$b</varname> est &true;.</entry>
</row>
</tbody>
</tgroup>
</table>
<simpara>
La raison pour laquelle il existe deux types de "ET" et de "OU"
est qu'ils ont des priorités différentes. Voir le
paragraphe
<link linkend="language.operators.precedence">précédence d'opérateurs</link>.
</simpara>
<example>
<title>Illustration des opérateurs logiques</title>
<programlisting role="php">
<![CDATA[
<?php
// --------------------
// foo() ne sera jamais appelée, car ces opérateurs s'annulent
$a = (false && foo());
$b = (true || foo());
$c = (false and foo());
$d = (true or foo());
// --------------------
// "||" a une précédence supérieure à "or"
// Le résultat de l'expression (false || true) est affecté à $e
// Agit comme : ($e = (false || true))
$e = false || true;
// La constante false est affectée à $f avant que l'opération "or" apparaisse
// Agit comme : (($f = false) or true)
$f = false or true;
var_dump($e, $f);
// --------------------
// "&&" a une précédence supérieure à "and"
// Le résultat de l'expression (true && false) est affecté à $g
// Agit comme : ($g = (true && false))
$g = true && false;
// La constante true est affectée à $h avant que l'opération "and" apparaisse
// Agit comme : (($h = true) and false)
$h = true and false;
var_dump($g, $h);
?>
]]>
</programlisting>
&example.outputs.similar;
<screen>
<![CDATA[
bool(true)
bool(false)
bool(false)
bool(true)
]]>
</screen>
</example>
</sect1>
<sect1 xml:id="language.operators.string">
<title>Opérateurs de chaînes</title>
<simpara>
Il y a deux opérateurs de chaînes de caractères <type>string</type>.
Le premier est l'opérateur de concaténation ('.'), qui
retourne la concaténation de ses deux arguments.
Le second est l'opérateur d'affectation
concaténant (<literal>.=</literal>). Reportez-vous à
<link linkend="language.operators.assignment">opérateurs d'affectation</link>
pour plus de détails.
</simpara>
<para>
<example>
<title>Opérateur de concaténation</title>
<programlisting role="php">
<![CDATA[
<?php
$a = "Bonjour ";
$b = $a . "Monde !"; // $b contient "Bonjour Monde !"
$a = "Bonjour ";
$a .= "Monde !"; // $a contient "Bonjour Monde !"
?>
]]>
</programlisting>
</example>
</para>
<sect2 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member><link linkend="language.types.string">Les types de chaînes de caractères</link></member>
<member><link linkend="ref.strings">Les fonctions de chaînes de caractères</link></member>
</simplelist>
</para>
</sect2>
</sect1>
<sect1 xml:id="language.operators.array">
<title>Opérateurs de tableaux</title>
<table>
<title>Opérateurs de tableaux</title>
<tgroup cols="3">
<thead>
<row>
<entry>Exemple</entry>
<entry>Nom</entry>
<entry>Résultat</entry>
</row>
</thead>
<tbody>
<row>
<entry>$a + $b</entry>
<entry>Union</entry>
<entry>Union de <varname>$a</varname> et <varname>$b</varname>.</entry>
</row>
<row>
<entry>$a == $b</entry>
<entry>Égalité</entry>
<entry>&true; si <varname>$a</varname> et <varname>$b</varname> contiennent les mêmes paires clés/valeurs.</entry>
</row>
<row>
<entry>$a === $b</entry>
<entry>Identique</entry>
<entry>&true; si <varname>$a</varname> et <varname>$b</varname> contiennent les mêmes paires clés/valeurs dans le même ordre et du même type.</entry>
</row>
<row>
<entry>$a != $b</entry>
<entry>Inégalité</entry>
<entry>&true; si <varname>$a</varname> n'est pas égal à <varname>$b</varname>.</entry>
</row>
<row>
<entry>$a &lt;&gt; $b</entry>
<entry>Inégalité</entry>
<entry>&true; si <varname>$a</varname> n'est pas égal à <varname>$b</varname>.</entry>
</row>
<row>
<entry>$a !== $b</entry>
<entry>Non-identique</entry>
<entry>&true; si <varname>$a</varname> n'est pas identique à <varname>$b</varname>.</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
L'opérateur <literal>+</literal> retourne le tableau de gauche auquel sont
ajoutés les éléments du tableau de droite. Pour les clés présentes dans les
2 tableaux, les éléments du tableau de gauche seront utilisés alors que les
éléments correspondants dans le tableau de droite seront ignorés.
</para>
<para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$a = array("a" => "pomme", "b" => "banane");
$b = array("a" =>"poire", "b" => "fraise", "c" => "cerise");
$c = $a + $b; // Union de $a et $b
echo "Union de \$a et \$b : \n";
var_dump($c);
$c = $b + $a; // Union de $b et $a
echo "Union de \$b et \$a : \n";
var_dump($c);
$a += $b; // Union de $a += $b est $a and $b
echo "Union de \$a += \$b: \n";
var_dump($a);
?>
]]>
</programlisting>
</informalexample>
À l'exécution, le script affichera :
<screen role="php">
<![CDATA[
Union de $a et $b :
array(3) {
["a"]=>
string(5) "pomme"
["b"]=>
string(6) "banane"
["c"]=>
string(6) "cerise"
}
Union de $b et $a :
array(3) {
["a"]=>
string(5) "poire"
["b"]=>
string(6) "fraise"
["c"]=>
string(6) "cerise"
}
Union de $a += $b:
array(3) {
["a"]=>
string(5) "pomme"
["b"]=>
string(6) "banane"
["c"]=>
string(6) "cerise"
}
]]>
</screen>
</para>
<para>
Les éléments d'un tableau sont égaux en termes de comparaison s'ils ont la
même clé et la même valeur.
</para>
<para>
<example>
<title>Comparer des tableaux</title>
<programlisting role="php">
<![CDATA[
<?php
$a = array("pomme", "banane");
$b = array(1 => "banane", "0" => "pomme");
var_dump($a == $b); // bool(true)
var_dump($a === $b); // bool(false)
?>
]]>
</programlisting>
</example>
</para>
<sect2 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member><link linkend="language.types.array">Le Type Tableau</link></member>
<member><link linkend="ref.array">Les Fonctions de Tableaux</link></member>
</simplelist>
</para>
</sect2>
</sect1>
<sect1 xml:id="language.operators.type">
<title>Opérateurs de types</title>
<para>
<literal>instanceof</literal> est utilisé pour déterminer si une variable PHP
est un objet instancié d'une certaine
<link linkend="language.oop5.basic.class">classe</link> :
<example>
<title>Utilisation de <literal>instanceof</literal> avec des classes</title>
<programlisting role="php">
<![CDATA[
<?php
class MaClasse
{
}
class PasMaClasse
{
}
$a = new MaClasse;
var_dump($a instanceof MaClasse);
var_dump($a instanceof PasMaClasse);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
bool(true)
bool(false)
]]>
</screen>
</example>
</para>
<para>
<literal>instanceof</literal> peut également être utilisé pour déterminer
si une variable est un objet instancié d'une classe qui hérite d'une classe parente :
<example>
<title>Utilisation de <literal>instanceof</literal> avec des classes héritées</title>
<programlisting role="php">
<![CDATA[
<?php
class ParentClass
{
}
class MyClass extends ParentClass
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof ParentClass);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
bool(true)
bool(true)
]]>
</screen>
</example>
</para>
<para>
Pour vérifier si un objet <emphasis>n'est pas</emphasis> une instance d'une classe,
l'<link linkend="language.operators.logical">opérateur logique <literal>not</literal></link>
peut être utilisé.
<example>
<title>Utilisation de <literal>instanceof</literal> pour vérifier que l'objet
<emphasis>n'est pas</emphasis> une instance de la classe</title>
<programlisting role="php">
<![CDATA[
<?php
class MyClass
{
}
$a = new MyClass;
var_dump(!($a instanceof stdClass));
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
bool(true)
]]>
</screen>
</example>
</para>
<para>
Et finalement, <literal>instanceof</literal> peut être utilisé pour déterminer
si une variable est un objet instancié d'une classe qui implémente une
<link linkend="language.oop5.interfaces">interface</link> :
<example>
<title>Utilisation de <literal>instanceof</literal> pour une interface</title>
<programlisting role="php">
<![CDATA[
<?php
interface MyInterface
{
}
class MyClass implements MyInterface
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof MyInterface);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
bool(true)
bool(true)
]]>
</screen>
</example>
</para>
<para>
Bien que <literal>instanceof</literal> soit habituellement utilisé avec un nom
de classe littéral, il peut également être utilisé avec un autre objet ou une chaîne
représentant une variable :
<example>
<title>Utilisation de <literal>instanceof</literal> avec d'autres variables</title>
<programlisting role="php">
<![CDATA[
<?php
interface MyInterface
{
}
class MyClass implements MyInterface
{
}
$a = new MyClass;
$b = new MyClass;
$c = 'MyClass';
$d = 'NotMyClass';
var_dump($a instanceof $b); // $b est un objet de la classe MyClass
var_dump($a instanceof $c); // $c est une chaîne 'MyClass'
var_dump($a instanceof $d); // $d est une chaîne 'NotMyClass'
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
bool(true)
bool(true)
bool(false)
]]>
</screen>
</example>
</para>
<para>
instanceof ne lance aucune erreur si la variable testée n'est pas
un objet, il retournera simplement &false;. Cependant, les constantes
ne sont pas autorisées.
<example>
<title>Utilisation de <literal>instanceof</literal> pour tester d'autres variables</title>
<programlisting role="php">
<![CDATA[
<?php
$a = 1;
$b = NULL;
$c = imagecreate(5, 5);
var_dump($a instanceof stdClass); // $a est un entier
var_dump($b instanceof stdClass); // $b vaut NULL
var_dump($c instanceof stdClass); // $c est une ressource
var_dump(FALSE instanceof stdClass);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
bool(false)
bool(false)
bool(false)
PHP Fatal error: instanceof expects an object instance, constant given
]]>
</screen>
</example>
</para>
<para>
À partir de PHP 7.3.0, les constantes sont autorisées sur le côté gauche
de l'opérateur <literal>instanceof</literal>.
<example>
<title>Utilisation de <literal>instanceof</literal> pour tester des constantes</title>
<programlisting role="php">
<![CDATA[
<?php
var_dump(FALSE instanceof stdClass);
?>
]]>
</programlisting>
&example.outputs.73;
<screen>
<![CDATA[
bool(false)
]]>
</screen>
</example>
</para>
<para>
À partir de PHP 8.0.0, <literal>instanceof</literal> peut désormais être
utilisé avec des expressions arbitraires.
L'expression doit être entre parenthèses et produire une <type>string</type>.
<!-- RFC: https://wiki.php.net/rfc/variable_syntax_tweaks -->
<example>
<title>Utilisation de <literal>instanceof</literal> avec une expression arbitraire</title>
<programlisting role="php">
<![CDATA[
<?php
class ClassA extends \stdClass {}
class ClassB extends \stdClass {}
class ClassC extends ClassB {}
class ClassD extends ClassA {}
function getSomeClass(): string
{
return ClassA::class;
}
var_dump(new ClassA instanceof ('std' . 'Class'));
var_dump(new ClassB instanceof ('Class' . 'B'));
var_dump(new ClassC instanceof ('Class' . 'A'));
var_dump(new ClassD instanceof (getSomeClass()));
?>
]]>
</programlisting>
&example.outputs.8;
<screen>
<![CDATA[
bool(true)
bool(true)
bool(false)
bool(true)
]]>
</screen>
</example>
</para>
<simpara>
L'opérateur <literal>instanceof</literal> a une variante fonctionnelle
avec la fonction <function>is_a</function>.
</simpara>
<sect2 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member><function>get_class</function></member>
<member><function>is_a</function></member>
</simplelist>
</para>
</sect2>
</sect1>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->