Files
doc-fr/language/operators.xml
T
Damien Seguy c7eec5cdd7 synch with en
git-svn-id: https://svn.php.net/repository/phpdoc/fr/trunk@278321 c90b9560-bf6c-de11-be94-00142212c4b1
2009-04-06 19:13:31 +00:00

1549 lines
47 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision: 1.111 $ -->
<!-- EN-Revision: 1.135 Maintainer: yannick Status: ready -->
<!-- Reviewed: yes -->
<chapter xml:id="language.operators" xmlns="http://docbook.org/ns/docbook">
<title>Les opérateurs</title>
<simpara>
Un opérateur est quelque chose que vous alimentez avec une ou plusieurs
valeurs (ou expression, dans le jargon de programmation) qui retourne une
autre valeur (donc que la construction elle-même devient une expression).
Donc, vous pouvez penser aux fonctions ou constructions qui retournent une
valeur (comme <function>print</function>) comme opérateur et celles qui
retournent rien du tout (comme <function>echo</function>).
</simpara>
<para>
Il y a trois types d'opérateurs. Le premier, l'opérateur unaire, qui opère
sur une seule valeur, par exemple ! (l'opérateur de négation) ou ++
(l'opérateur d'incrémentation). Le second groupe, les opérateurs binaires ;
ce groupe contient la plupart des opérateurs supportés par PHP qui sont
listés ci-dessous dans la section
"<link linkend="language.operators.precedence">La précédence des opérateurs</link>".
</para>
<para>
Le troisième groupe est le groupe des opérateurs de terminaison : ?:.
Ils doivent être utilisés pour choisir entre deux expressions dépendantes
d'une troisième, plutôt que sélectionner deux phrases ou chemins d'exécution.
Les expressions ternaires environnantes avec des parenthèses sont une très bonne idée.
</para>
<sect1 xml:id="language.operators.precedence">
<title>La précédence 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>. Si la priorité d'opérateur est égale,
l'associativité de gauche à droite est utilisée.
</para>
<para>
Le tableau suivant dresse une liste de la priorité des différents
opérateurs dans un ordre décroissant de priorité. Les opérateurs sur une
même ligne ont une priorité équivalente et, dans ce cas, leur association
décide de l'ordre de leur évaluation.
<table>
<title>Précédence 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>non-associative</entry>
<entry>clone new</entry>
<entry><link linkend="language.oop5.cloning">clone</link> et <link linkend="language.oop5.basic.new">new</link></entry>
</row>
<row>
<entry>gauche</entry>
<entry>[</entry>
<entry><function>array</function></entry>
</row>
<row>
<entry>non-associatif</entry>
<entry>++ --</entry>
<entry>
<link linkend="language.operators.increment">incrémentation/décrémentation</link>
</entry>
</row>
<row>
<entry>non-associatif</entry>
<entry>~ - (int) (float) (string) (array) (object) (bool) @</entry>
<entry>
<link linkend="language.types">types</link>
</entry>
</row>
<row>
<entry>non-associatif</entry>
<entry>instanceof</entry>
<entry>
<link linkend="language.types">types</link>
</entry>
</row>
<row>
<entry>droite</entry>
<entry>!</entry>
<entry>
<link linkend="language.operators.logical">logique</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry>* / %</entry>
<entry>
<link linkend="language.operators.arithmetic">arithmétique</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry>+ - .</entry>
<entry>
<link linkend="language.operators.arithmetic">arithmétique</link>&listendand;
<link linkend="language.operators.string">chaîne de caractères</link></entry>
</row>
<row>
<entry>gauche</entry>
<entry>&lt;&lt; &gt;&gt;</entry>
<entry>
<link linkend="language.operators.bitwise">bitwise</link>
</entry>
</row>
<row>
<entry>non-associatif</entry>
<entry>&lt; &lt;= &gt; &gt;= &lt;&gt;</entry>
<entry>
<link linkend="language.operators.comparison">comparaison</link>
</entry>
</row>
<row>
<entry>non-associatif</entry>
<entry>== != === !==</entry>
<entry>
<link linkend="language.operators.comparison">comparaison</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry>&amp;</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>^</entry>
<entry>
<link linkend="language.operators.bitwise">bitwise</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry>|</entry>
<entry>
<link linkend="language.operators.bitwise">bitwise</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry>&amp;&amp;</entry>
<entry>
<link linkend="language.operators.logical">logique</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry>||</entry>
<entry>
<link linkend="language.operators.logical">logique</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry>? :</entry>
<entry>
<link linkend="language.operators.comparison.ternary">ternaire</link>
</entry>
</row>
<row>
<entry>droite</entry>
<entry>
= += -= *= /= .= %= &amp;= |= ^= &lt;&lt;= &gt;&gt;=
</entry>
<entry>
<link linkend="language.operators.assignment">assignation</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry>and</entry>
<entry>
<link linkend="language.operators.logical">logique</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry>xor</entry>
<entry>
<link linkend="language.operators.logical">logique</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry>or</entry>
<entry>
<link linkend="language.operators.logical">logique</link>
</entry>
</row>
<row>
<entry>gauche</entry>
<entry>,</entry>
<entry>plusieurs utilisations</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
L'associativité de gauche signifie que l'expression est évaluée de gauche
à droite, l'associativité de droite, l'inverse.
<example>
<title>Associativité</title>
<programlisting role="php">
<![CDATA[
<?php
$a = 3 * 3 % 5; // (3 * 3) % 5 = 4
$a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2
$a = 1;
$b = 2;
$a = $b += 3; // $a = ($b += 3) -> $a = 5, $b = 5
?>
]]>
</programlisting>
</example>
Utilisez les parenthèses pour augmenter la lisibilité du code.
</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>
</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>Négation</entry>
<entry>Opposé de $a.</entry>
</row>
<row>
<entry><literal>$a + $b</literal></entry>
<entry>Addition</entry>
<entry>Somme de <varname>$a</varname> et <varname>$b</varname>.</entry>
</row>
<row>
<entry><literal>$a - $b</literal></entry>
<entry>Soustraction</entry>
<entry>
Différence de <varname>$a</varname> et <varname>$b</varname>.
</entry>
</row>
<row>
<entry><literal>$a * $b</literal></entry>
<entry>Multiplication</entry>
<entry>Produit de <varname>$a</varname> et <varname>$b</varname>.</entry>
</row>
<row>
<entry><literal>$a / $b</literal></entry>
<entry>Division</entry>
<entry>
Quotient de <varname>$a</varname> et <varname>$b</varname>.
</entry>
</row>
<row>
<entry><literal>$a % $b</literal></entry>
<entry>Modulo</entry>
<entry>
Reste de <varname>$a</varname> divisé par <varname>$b</varname>.
</entry>
</row>
</tbody>
</tgroup>
</table>
<simpara>
L'opérateur de division ("/") retourne une valeur entière
(le résultat d'une division entière) si les deux opérandes
sont entiers (ou bien des chaînes converties en entier).
</simpara>
<simpara>
Les opérandes du modulo sont converties en entiers (en supprimant la partie
décimale) avant exécution.
</simpara>
<note>
<simpara>
Souvenez-vous que <literal>$a % $b</literal> est négatif si
<literal>$a</literal> est négatif.
</simpara>
</note>
<simpara>
Voir aussi le manuel sur les
<link linkend="ref.math">fonctions mathématiques</link>.
</simpara>
</sect1>
<sect1 xml:id="language.operators.assignment">
<title>Les opérateurs d'assignation</title>
<simpara>
L'opérateur d'assignation 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'assignation est la valeur
assigné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'assignation, 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'assignation copie le contenu de la variable originale
dans la nouvelle variable (assignation 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. L'assignation par référence est également supportée, en
utilisant la syntaxe <computeroutput>$var = &amp;$othervar;</computeroutput>.
L'assignation par référence' signifie que les deux variables contiennent les
mêmes données, et que la modification de l'une affecte
l'autre et rien n'est copié nul part. Pour plus d'informations sur
les références, lisez
<link linkend="language.references">l'explication sur les références</link>.
Depuis PHP 5, les objets sont assignés par référence, sans une demande spécifique
du contraire en utilisant le nouveau mot clé <link linkend="language.oop5.cloning">clone</link>.
</para>
</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. Si les paramètres de gauche et de droite
sont des chaînes de caractères, l'opérateur de bits agira sur les
valeurs ASCII de ces caractères.
</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>ET (<literal>And</literal>)</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 (<literal>Ou</literal>)</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>NON (<literal>Not</literal>)</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écalage des bits de <varname>$a</varname>, <varname>$b</varname> fois
par la droite (chaque décalage équivaut à une division par 2).
</entry>
</row>
</tbody>
</tgroup>
</table>
<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
--------- --------- -- ---------
resultat 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[
--------- --------- -- ---------
resultat 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>
<warning>
<para>
N'effectuez pas de décalage à droite de plus de 32 bits sur les systèmes
32 bits. N'effectuez pas de décalage à droite dans le cas où le résultat
est un nombre plus long que 32 bits.
</para>
</warning>
</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><userinput>$a == $b</userinput></entry>
<entry>Egal</entry>
<entry>&true; si <varname>$a</varname> est égal à
<varname>$b</varname>.</entry>
</row>
<row>
<entry><userinput>$a === $b</userinput></entry>
<entry>Identique</entry>
<entry>
&true; si <varname>$a</varname> est égal à <varname>$b</varname> et
qu'ils sont de même type (introduit en PHP 4).
</entry>
</row>
<row>
<entry><userinput>$a != $b</userinput></entry>
<entry>Différent</entry>
<entry>&true; si <varname>$a</varname> est différent de
<varname>$b</varname>.</entry>
</row>
<row>
<entry><userinput>$a &lt;&gt; $b</userinput></entry>
<entry>Différent</entry>
<entry>&true; si <varname>$a</varname> est différent de
<varname>$b</varname>.</entry>
</row>
<row>
<entry><userinput>$a !== $b</userinput></entry>
<entry>Différent</entry>
<entry>
&true; si <varname>$a</varname> est différent de <varname>$b</varname>
ou bien qu'ils ne sont pas du même type. (introduit en PHP 4)
</entry>
</row>
<row>
<entry><userinput>$a &lt; $b</userinput></entry>
<entry>Plus petit que</entry>
<entry>&true; si <varname>$a</varname> est strictement plus petit que
<varname>$b</varname>.</entry>
</row>
<row>
<entry><literal>$a &gt; $b</literal></entry>
<entry>Plus grand</entry>
<entry>&true; si <varname>$a</varname> est strictement plus grand que
<varname>$b</varname>.</entry>
</row>
<row>
<entry><userinput>$a &lt;= $b</userinput></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><userinput>$a &gt;= $b</userinput></entry>
<entry>Supérieur ou égal</entry>
<entry>&true; si <varname>$a</varname> est plus grand ou égal à
<varname>$b</varname>.</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Si vous comparez un entier avec une chaîne, la chaîne est
<link linkend="language.types.string.conversion">convertie en un nombre</link>.
Si vous comparez deux chaînes numériques, elles seront comparées en tant
qu'entiers. Ces règles s'appliquent aussi à l'instruction
<link linkend="control-structures.switch">switch</link>.
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
var_dump(0 == "a"); // 0 == 0 -> true
var_dump("1" == "01"); // 1 == 1 -> true
var_dump("1" == "1e0"); // 1 == 1 -> true
switch ("a") {
case 0:
echo "0";
break;
case "a": // jamais évalué parce que "a" est déjà trouvé avec 0
echo "a";
break;
}
?>
]]>
</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>chaîne de caractères</type></entry>
<entry><type>string</type></entry>
<entry>Convertit &null; en "", comparaison numérique ou lexicale</entry>
</row>
<row>
<entry><type>booléen</type> ou <type>null</type></entry>
<entry>N'importe quoi</entry>
<entry>Convertit en <type>booléen</type>, &false; &lt; &true;</entry>
</row>
<row>
<entry><type>objet</type></entry>
<entry><type>objet</type></entry>
<entry>Les classes internes peuvent définir leur propre méthode de
comparaison; différentes classes ne sont pas comparables; entre objets
de même classe, la comparaison se fait de la même façon que pour les
tableaux (PHP 4), PHP 5 a son propre
<link linkend="language.oop5.object-comparison">comportement</link></entry>
</row>
<row>
<entry>
<type>chaîne de caractères</type>, <type>ressource</type> ou
<type>nombre</type>
</entry>
<entry>
<type>chaîne de caractères</type>, <type>ressource</type> ou
<type>nombre</type>
</entry>
<entry>
Transforme les chaînes de caractères et les ressources en nombres
</entry>
</row>
<row>
<entry><type>tableaux</type></entry>
<entry><type>tableaux</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 ne
sont pas comparables, sinon la comparaison se fait valeur par valeur
(voir l'exemple suivant)
</entry>
</row>
<row>
<entry><type>tableau</type></entry>
<entry>N'importe quoi</entry>
<entry>Le <type>tableau</type> est toujours plus grand</entry>
</row>
<row>
<entry><type>objet</type></entry>
<entry>N'importe quoi</entry>
<entry>L'<type>objet</type> est toujours plus grand</entry>
</row>
</tbody>
</tgroup>
</table>
<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
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 null; // incomparable
} elseif ($val < $op2[$key]) {
return -1;
} elseif ($val > $op2[$key]) {
return 1;
}
}
return 0; // $op1 == $op2
}
?>
]]>
</programlisting>
</example>
</para>
<para>
Voir aussi
<function>strcasecmp</function>,
<function>strcmp</function>
<link linkend="language.operators.array">les opérateurs de tableaux</link>,
et le chapitre sur les <link linkend="language.types">types</link>.
</para>
<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>Assignation 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>
Depuis PHP 5.3, il est possible d'omettre la partie centrale de l'opérateur
ternaire. L'expression <literal>expr1 ?: expr3</literal> retourne
<replaceable>expr1</replaceable> si <replaceable>expr1</replaceable>
vaut &true;, est <replaceable>expr3</replaceable> sinon.
</para>
<note>
<simpara>
Notez que l'opérateur ternaire est une instruction, et il n'est pas
évalué en tant que variable, mais en tant que résultat de l'instruction.
Il est important de 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 dans les versions supérieures de PHP.
</simpara>
</note>
<note>
<para>
Il est recommandé de ne pas "empiler" les expressions ternaires.
Le comportement de PHP lors de l'utilisation de plus d'un opérateur
ternaire dans une seule instruction n'est pas évident :
<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'
// car l'expression ternaire est évaluée de gauche à droite
// l'expression suivante est une version plus évidente du même code
echo ((true ? 'true' : 'false') ? 't' : 'f');
// ici, vous pouvez voir 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>
</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 : c'est @.
Lorsque cet opérateur est ajouté en préfixe d'une
expression PHP, les messages d'erreur qui peuvent être
générés par cette expression seront ignorés.
</simpara>
<simpara>
Si l'option
<link linkend="ini.track-errors"><option>track_errors</option></link>
est activée, les messages d'erreurs générés
par une expression seront sauvés dans la variable globale
<varname>$php_errormsg</varname>.
Cette variable sera écrasée à chaque erreur.
Il faut alors la surveiller souvent pour pouvoir l'utiliser.
</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 : '$php_errormsg'");
// 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 @ ne fonctionne qu'avec les
<link linkend="language.expressions">expressions</link>. La règle
générale de fonctionnement est la suivante : si vous pouvez prendre
la valeur de quelque chose, vous pouvez le préfixer avec @. Par exemple,
vous pouvez ajouter @ aux variables, fonctions, à
<function>include</function>, aux constantes, etc. Vous ne pourrez
pas le faire avec des éléments de langage tels que les classes,
<literal>if</literal> et &foreach;, etc.
</simpara>
</note>
<simpara>
Voir aussi
<function>error_reporting</function> et la section sur la
<link linkend="ref.errorfunc">gestion d'erreurs</link>.
</simpara>
<warning>
<para>
En fait, l'opérateur "@" va aussi désactiver les rapports
d'erreurs critiques, qui stoppent l'exécution du script. Entre autres,
si vous utilisez "@" pour supprimer les erreurs de certaines
fonctions, et que cette fonction n'existe pas, ou qu'elle
a été mal orthographiée, vous n'aurez aucune indication.
</para>
</warning>
</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é (i.e. : il ne sera pas simplement envoyé
à la sortie standard, il peut être assigné à une variable). Utilisez 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 le
&safemode; est activé ou bien que la fonction
<function>shell_exec</function> est désactivée.
</para>
</note>
<para>
Voir aussi le manuel à la section sur les
<link linkend="ref.exec">fonctions d'exécution système</link>,
<function>popen</function>,
<function>proc_open</function> et
<link linkend="features.commandline">l'utilisation de PHP en ligne de commande</link>.
</para>
</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 pas les valeurs
booléennes. La décrémentation des valeurs &null; n'a également aucun effet,
mais leur incrémentation donnera comme résultat &one;.
</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><literal>++$a</literal></entry>
<entry>Pre-incrémente</entry>
<entry>
Incrémente <varname>$a</varname> de 1, puis retourne
<varname>$a</varname>.
</entry>
</row>
<row>
<entry><literal>$a++</literal></entry>
<entry>Post-incrémente</entry>
<entry>Retourne <varname>$a</varname>, puis l'incrémente de 1.</entry>
</row>
<row>
<entry><literal>--$a</literal></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><literal>$a--</literal></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, et non pas celle du C. Par exemple, en Perl
<literal>'Z'+1</literal> retourne <literal>'AA'</literal>, alors qu'en C,
<literal>'Z'+1</literal> retourne <literal>'['</literal>
(<literal>ord('Z') == 90</literal>, donc <literal>ord('[') == 91</literal>).
Notez que les variables de caractères peuvent être incrémentées, mais pas
décrémentées et même seuls les caractères ASCII (a-z et A-Z) sont supportés.
<example>
<title>Opérations arithmétiques sur un caractère</title>
<programlisting role="php">
<![CDATA[
<?php
$i = 'W';
for($n=0; $n<6; $n++) {
echo ++$i . "\n";
}
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
X
Y
Z
AA
AB
AC
]]>
</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><literal>$a and $b</literal></entry>
<entry>ET (<literal>And</literal>)</entry>
<entry>&true; si <varname>$a</varname> ET <varname>$b</varname> valent &true;.</entry>
</row>
<row>
<entry><literal>$a or $b</literal></entry>
<entry>OU (<literal>Or</literal>)</entry>
<entry>&true; si <varname>$a</varname> OU <varname>$b</varname> valent &true;.</entry>
</row>
<row>
<entry><literal>$a xor $b</literal></entry>
<entry>XOR (<literal>Xor</literal>)</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><literal>! $a</literal></entry>
<entry>NON (<literal>Not</literal>)</entry>
<entry>&true; si <varname>$a</varname> n'est pas &true;.</entry>
</row>
<row>
<entry><literal>$a &amp;&amp; $b</literal></entry>
<entry>ET (<literal>And</literal>)</entry>
<entry>&true; si <varname>$a</varname> ET <varname>$b</varname> sont &true;.</entry>
</row>
<row>
<entry><literal>$a || $b</literal></entry>
<entry>OU (<literal>Or</literal>)</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 appeler car ces opérateurs s'annulent
$a = (false && foo());
$b = (true || foo());
$c = (false and foo());
$d = (true or foo());
// "||" a un précédence supérieure que "or"
$e = false || true; // $e se vera assigner à (false || true), ce qui est true
$f = false or true; // $f se vera assigner à false
var_dump($e, $f);
// "&&" a une précédence supérieure à "and"
$g = true && false; // $g se vera assigner à (true && false), ce qui est false
$h = true and false; // $h se vera assigner à true
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'assignation
concaténant (<literal>.=</literal>). Reportez-vous à
<link linkend="language.operators.assignment">opérateurs d'assignation</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 = $a . "Monde !"; // $a contient "Bonjour Monde !"
?>
]]>
</programlisting>
</example>
</para>
<para>
Voir aussi les sections du manuel sur
<link linkend="language.types.string">les types de chaînes de caractères</link> et
<link linkend="ref.strings">les chaînes de caractères</link>.
</para>
</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><varname>$a + $b</varname></entry>
<entry>Union</entry>
<entry>Union de <varname>$a</varname> et <varname>$b</varname>.</entry>
</row>
<row>
<entry><varname>$a == $b</varname></entry>
<entry>Egalité</entry>
<entry>&true; si <varname>$a</varname> et <varname>$b</varname> contiennent les mêmes paires clés/valeurs.</entry>
</row>
<row>
<entry><varname>$a === $b</varname></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><varname>$a != $b</varname></entry>
<entry>Inégalité</entry>
<entry>&true; si <varname>$a</varname> n'est pas égal à <varname>$b</varname>.</entry>
</row>
<row>
<entry><varname>$a &lt;&gt; $b</varname></entry>
<entry>Inégalité</entry>
<entry>&true; si <varname>$a</varname> n'est pas égal à <varname>$b</varname>.</entry>
</row>
<row>
<entry><varname>$a !== $b</varname></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> ajoute les éléments du tableau
de droite au tableau de gauche, sans pour autant écrasées les clés
communes.
</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);
?>
]]>
</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"
}
]]>
</screen>
</para>
<para>
Les éléments d'un tableau sont égaux en terme
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>
<para>
Voyez aussi le manuel aux sections
<link linkend="language.types.array">Tableaux</link> et
<link linkend="ref.array">fonctions de tableaux</link>.
</para>
</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 instanceof 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 n'est <emphasis>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></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 classe</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>
Il y a quelque piège à éviter. Avant PHP version 5.1.0,
<literal>instanceof</literal> appellera <link linkend="language.oop5.autoload">__autoload()</link>
si le nom de la classe n'existe pas. De plus, si la classe n'a pas été chargée,
une erreur fatale sera émise. Ceci peut fonctionner en utilisant une référence
de classe dynamique, ou une chaîne représentant une variable contenant le nom
de la classe :
<example>
<title>Pas de recherche sur le nom de la classe et une erreur fatale avec
<literal>instanceof</literal> en PHP 5.0</title>
<programlisting role="php">
<![CDATA[
<?php
$d = 'NotMyClass';
var_dump($a instanceof $d); // no fatal error here
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
bool(false)
]]>
</screen>
</example>
</para>
<simpara>
L'opérateur <literal>instanceof</literal> a été introduit en PHP 5.
Avant cette version, <function>is_a</function> était utilisé mais
<function>is_a</function> est depuis devenu obsolète, en faveur de
<literal>instanceof</literal>. Notez que depuis PHP 5.3.0,
<function>is_a</function> n'est de nouveau plus obsolète.
</simpara>
<para>
Voir aussi
<function>get_class</function> et
<function>is_a</function>.
</para>
</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:"../manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->