Les expressions sont les pièces de construction les plus importantes de PHP. En PHP, presque tout ce qui s'écrit est une expression. La manière la plus simple de définir une expression est : "tout ce qui a une valeur".
Les formes les plus simples d'expressions sont les constantes et les variables.
Lorsque l'on écrit $a = 5, on assigne la valeur 5
à la variable $a. Bien évidemment, 5 vaut 5 ou,
en d'autres termes, 5 est une expression avec pour valeur 5
(dans ce cas, 5 est un entier constant).
Après cette assignation, on peut considérer que $a
a pour valeur 5 et donc, écrire $b = $a, revient à écrire
$b = 5. En d'autres termes, $a est une
expression avec une valeur de 5. Si tout fonctionne correctement,
c'est exactement ce qui arrive.
Un exemple plus complexe concerne les fonctions. Par exemple, considérons la fonction suivante :
<?php
function foo ()
{
return 5;
}
?>
En supposant une familiarité avec le concept de fonction,
(si ce n'est pas le cas, consulter le chapitre concernant les
fonctions),
on conviendra que $c = foo() est équivalent
à $c = 5, et
c'est tout à fait exact. Les fonctions sont des expressions qui
ont la valeur de leur "valeur de retour". Si foo()
renvoie 5, la valeur de l'expression foo() est 5.
Habituellement, les fonctions ne font pas que
renvoyer une valeur constante, mais réalisent des traitements.
Bien sûr, les valeurs en PHP n'ont pas à être des valeurs numériques, comme c'est souvent le cas. PHP supporte quatre types de variables scalaires : les valeurs entières (entier), les nombres à virgule flottante (float ), les chaînes de caractères (chaîne de caractères) et les booléens (bool ). (une variable scalaire est une variable qui ne peut pas être scindée en morceaux, au contraire des tableaux par exemple). PHP supporte aussi deux types composés : les tableaux et les objets. Chacun de ces types de variables peut être affecté ou renvoyé par une fonction.
PHP va plus loin dans la gestion des expressions, comme le font d'autres
langages. PHP est un langage orienté expression, dans le sens où
presque tout est une expression. Considérons l'exemple dont nous avons
déjà parlé, $a = 5. Il est facile de voir qu'il y a
deux valeurs qui entrent en jeu ici, la valeur de la constante entière 5
et la valeur de la variable $a qui est mise à jour à la
valeur 5. Mais, la vérité est qu'il y a une autre valeur qui entre en jeu
ici et c'est la valeur de l'assignation elle-même. L'assignation elle-même
est assignée à une valeur, dans ce cas-là 5. En pratique,
cela signifie que $a = 5 est une expression qui a pour
valeur 5. Donc, écrire $b = ($a = 5)
revient à écrire $a = 5; $b = 5;
(un point-virgule marque la fin d'une instruction). Comme les assignations
sont analysées de droite à gauche, il est aussi possible d'écrire
$b = $a = 5.
Un autre bon exemple du langage orienté expression est la
pre-incrémentation et la post-incrémentation, (ainsi que
la décrémentation). Les utilisateurs de PHP
et ceux de nombreux autres langages sont habitués à
la notation variable++ et
variable--.
Ce sont les opérateurs
d'incrémentation et de décrémentation. PHP
ajoute les possibilités d'incrémentation et de décrémentation
comme c'est le cas dans le langage C. En PHP, comme en C, il y a deux
types d'opérateurs d'incrémentation (pre-incrémentation et
post-incrémentation). Les deux types d'opérateur
d'incrémentation jouent le même rôle (c'est-à-dire qu'ils
incrémentent la variable). La différence vient de la valeur de
l'opérateur d'incrémentation. L'opérateur de
pre-incrémentation, qui s'écrit ++$variable, évalue
la valeur incrémentée (PHP incrémente la variable
avant de lire la valeur de cette variable, d'où le nom de
pre-incrémentation). L'opérateur de post-incrémentation,
qui s'écrit $variable++ , évalue la valeur de la
variable $variable avant de l'incrémenter (PHP incrémente la variable après
avoir lu sa valeur, d'où le nom de post-incrémentation).
Un type d'expression très commun est l'expression de comparaison. Ces
expressions sont évaluées à false ou true ,
respectivement. PHP supporte les opérateurs de comparaison > (plus
grand que), >= (plus grand ou égal), == (égal à),
!= (différent de), < (plus petit que) et <= (plus petit ou égal).
Le langage supporte également un ensemble d'opérateurs d'équivalence stricte : ===
(égal à et du même type) et !== (différent de ou pas du même type).
Ces expressions sont
utilisées de manière courante dans les instructions conditionnelles, comme
l'instruction if.
Pour le dernier exemple d'expression, nous allons parler des combinaisons
d'opérateurs/assignation. Pour incrémenter la
variable $a d'une unité, il suffit d'écrire
$a++ ou ++$a.
Mais pour ajouter la valeur 3 à la
variable ? Il est possible d'écrire plusieurs fois $a++, mais
ce n'est pas la meilleure des méthodes. Une pratique plus courante est
d'écrire $a = $a + 3. L'expression $a + 3
correspond à la valeur $a plus 3,
et est de nouveau assignée à la variable $a.
Donc, le résultat est l'incrémentation de 3 unités de la variable $a.
En PHP, comme dans de nombreux autres langages comme le C, il est possible d'écrire cela de manière plus
concise, manière qui avec le temps se révélera plus claire et plus rapide
à comprendre. Ajouter 3 à la valeur de la variable $a
peut s'écrire $a += 3. Cela signifie précisément : "on
prend la valeur de la variable $a, on ajoute la valeur 3
et on assigne cette valeur à la variable $a". Et pour
être plus concis et plus clair, cette expression est plus rapide. La valeur
de l'expression $a += 3, comme l'assignation d'une
valeur quelconque, est la valeur assignée. Il est à noter que ce n'est pas 3,
mais la combinaison de la valeur de la variable $a plus
la valeur 3. (c'est la valeur qui est assignée à la variable
$a). N'importe quel opérateur binaire
peut utiliser ce type d'assignation, par exemple $a -= 5
(soustraction de 5 de la valeur de la variable $a),
$b *= 7 (multiplication de la valeur de la variable
$b par 7).
Il y a une autre expression qui peut paraître complexe si elle n'a pas été vue dans d'autres langages, l'opérateur conditionnel ternaire :
<?php
$first ? $second : $third
?>
Si la valeur de la première sous-expression est vraie (true )
(différente de 0), alors la deuxième sous-expression est
évaluée et constitue le résultat de l'expression
conditionnelle. Sinon, c'est la troisième sous-expression qui est
évaluée et qui constitue le résultat de l'expression.
Les exemples suivants devraient permettre de mieux comprendre la pre-incrémentation, la post-incrémentation et le concept des expressions en général :
<?php
function double($i)
{
return $i * 2;
}
$b = $a = 5; /* Assigne la valeur 5 aux variables $a et $b */
$c = $a++; /* Post-incrémentation de la variable $a et assignation de
la valeur à la variable $c */
print "a = {$a}; b = {$b}; c = {$c}" . PHP_EOL;
$e = $d = ++$b; /* Pre-incrémentation, et assignation de la valeur aux
variables $d et $e */
print "b = {$b}; d = {$d}; e = {$e}" . PHP_EOL;
/* à ce niveau, les variables $d et $e sont égales à 6 */
$f = double($d++); /* assignation du double de la valeur de $d à la variable $f ($f vaut 12),
puis incrémentation de la valeur de $d */
print "d = {$d}; f = {$f}" . PHP_EOL;
$g = double(++$e); /* assigne deux fois la valeur de $e après
incrémentation, 2*7 = 14 à $g */
print "e = {$e}; g = {$g}" . PHP_EOL;
$h = $g += 10; /* Tout d'abord, $g est incrémentée de 10, et donc $g vaut 24.
Ensuite, la valeur de $g, (24) est assignée à la variable $h,
qui vaut donc elle aussi 24. */
print "g = {$g}; h = {$h}" . PHP_EOL;
?>
Au début de ce chapitre, nous avons dit que nous allions décrire les
différents types d'instructions, et donc, comme promis, nous allons voir que
les expressions peuvent être des instructions. Mais attention, toutes les
expressions ne sont pas des instructions. Dans ce cas-là, une instruction
est de la forme 'expr ;', c'est-à-dire, une expression
suivie par un point-virgule.
Dans $b = $a = 5;, $a = 5 est une expression valide,
mais ce n'est pas une instruction en elle-même.
$b = $a = 5; est une instruction valide.
La dernière chose qui mérite d'être mentionnée est
la véritable valeur des expressions. Lors de tests
sur une variable, dans une boucle conditionnelle par exemple, il n'est pas
nécessaire de savoir quelle est la valeur exacte de l'expression.
Seul importe de savoir si le résultat signifie true ou false .
Les constantes true et false (insensible à la casse) sont les deux
valeurs possibles pour un booléen. Lorsque nécessaire, une expression
est automatiquement convertie en booléen. Consulter la
section sur le transtypage
pour plus de détails.
PHP propose une implémentation complète et détaillée des expressions, et la documenter entièrement va au-delà de la portée de ce manuel. Les exemples ci-dessus devraient donner une bonne idée de ce qu'est une expression et comment construire des expressions utiles. Dans tout le reste de ce manuel, nous écrirons expr pour indiquer toute expression PHP valide.
Note that even though PHP borrows large portions of its syntax from C, the ',' is treated quite differently. It's not possible to create combined expressions in PHP using the comma-operator that C has, except in for() loops.
Example (parse error):
<?php
$a = 2, $b = 4;
echo $a."\n";
echo $b."\n";
?>
Example (works):
<?php
for ($a = 2, $b = 4; $a < 3; $a++)
{
echo $a."\n";
echo $b."\n";
}
?>
This is because PHP doesn't actually have a proper comma-operator, it's only supported as syntactic sugar in for() loop headers. In C, it would have been perfectly legitimate to have this:
int f()
{
int a, b;
a = 2, b = 4;
return a;
}
or even this:
int g()
{
int a, b;
a = (2, b = 4);
return a;
}
In f(), a would have been set to 2, and b would have been set to 4.
In g(), (2, b = 4) would be a single expression which evaluates to 4, so both a and b would have been set to 4.Manual defines "expression is anything that has value", Therefore, parser will give error for following code.
<?php
($val) ? echo('true') : echo('false');
Note: "? : " operator has this syntax "expr ? expr : expr;"
?>
since echo does not have(return) value and ?: expects expression(value).
However, if function/language constructs that have/return value, such as include(), parser compiles code.
Note: User defined functions always have/return value without explicit return statement (returns NULL if there is no return statement). Therefore, user defined functions are always valid expressions.
[It may be useful to have VOID as new type to prevent programmer to use function as RVALUE by mistake]
For example,
<?php
($val) ? include('true.inc') : include('false.inc');
?>
is valid, since "include" returns value.
The fact "echo" does not return value(="echo" is not a expression), is less obvious to me.
Print() and Echo() is NOT identical since print() has/returns value and can be a valid expression.Note that there is a difference between a function and a function call, and both
are expressions. PHP has two kinds of function, "named functions" and "anonymous
functions". Here's an example with both:
<?php
// A named function. Its name is "double".
function double($x) {
return 2 * $x;
}
// An anonymous function. It has no name, in the same way that the string
// "hello" has no name. Since it is an expression, we can give it a temporary
// name by assigning it to the variable $triple.
$triple = function($x) {
return 3 * $x;
};
?>
We can "call" (or "run") both kinds of function. A "function call" is an
expression with the value of whatever the function returns. For example:
<?php
// The easiest way to run a function is to put () after its name, containing its
// arguments (if any)
$my_numbers = array(double(5), $triple(5));
?>
$my_numbers is now an array containing 10 and 15, which are the return values of
double and $triple when applied to the number 5.
Importantly, if we *don't* call a function, ie. we don't put () after its name,
then we still get expressions. For example:
<?php
$my_functions = array('double', $triple);
?>
$my_functions is now an array containing these two functions. Notice that named
functions are more awkward than anonymous functions. PHP treats them differently
because it didn't use to have anonymous functions, and the way named functions
were implemented didn't work for anonymous functions when they were eventually
added.
This means that instead of using a named function literally, like we can with
anonymous functions, we have to use a string containing its name instead. PHP
makes sure that these strings will be treated as functions when it's
appropriate. For example:
<?php
$temp = 'double';
$my_number = $temp(5);
?>
$my_number will be 10, since PHP has spotted that we're treating a string as if
it were a function, so it has looked up that named function for us.
Unfortunately PHP's parser is very quirky; rather than looking for generic
patterns like "x(y)" and seeing if "x" is a function, it has lots of
special-cases like "$x(y)". This makes code like "'double'(5)" invalid, so we
have to do tricks like using temporary variables. There is another way around
this restriction though, and that is to pass our functions to the
"call_user_func" or "call_user_func_array" functions when we want to call them.
For example:
<?php
$my_numbers = array(call_user_func('double', 5), call_user_func($triple, 5));
?>
$my_numbers contains 10 and 15 because "call_user_func" called our functions for
us. This is possible because the string 'double' and the anonymous function
$triple are expressions. Note that we can even use this technique to call an
anonymous function without ever giving it a name:
<?php
$my_number = call_user_func(function($x) { return 4 * $x; }, 5);
?>
$my_number is now 20, since "call_user_func" called the anonymous function,
which quadruples its argument, with the value 5.
Passing functions around as expressions like this is very useful whenever we
need to use a 'callback'. Great examples of this are array_map and array_reduce.It is worthy to mention that:
$n = 3;
$n * --$n
WILL RETURN 4 instead of 6.
It can be a hard to spot "error", because in our human thought process this really isn't an error at all! But you have to remember that PHP (as it is with many other high-level languages) evaluates its statements RIGHT-TO-LEFT, and therefore "--$n" comes BEFORE multiplying, so - in the end - it's really "2 * 2", not "3 * 2".
It is also worthy to mention that the same behavior will change:
$n = 3;
$n * $n++
from 3 * 3 into 3 * 4. Post- operations operate on a variable after it has been 'checked', but it doesn't necessarily state that it should happen AFTER an evaluation is over (on the contrary, as a matter of fact).
So, if you ever find yourself on a 'wild goose chase' for a bug in that "impossible-to-break, so-very-simple" piece of code that uses pre-/post-'s, remember this post. :)
(just thought I'd check it out - turns out I was right :P)reply to egonfreeman at gmail dot com
04-Apr-2007 07:45
the second example u mentioned as follow:
=====================================
$n = 3;
$n * $n++
from 3 * 3 into 3 * 4. Post- operations operate on a variable after it has been 'checked', but it doesn't necessarily state that it should happen AFTER an evaluation is over (on the contrary, as a matter of fact).
===========================================
everything works correctly but one sentence should be modified:
"from 3 * 3 into 3 * 4" should be "from 3 * 3 into 4 * 3"
best regards~ :)A note about the short-circuit behaviour of the boolean operators.
1. if (func1() || func2())
Now, if func1() returns true, func2() isn't run, since the expression
will be true anyway.
2. if (func1() && func2())
Now, if func1() returns false, func2() isn't run, since the expression
will be false anyway.
The reason for this behaviour comes probably from the programming
language C, on which PHP seems to be based on. There the
short-circuiting can be a very useful tool. For example:
int * myarray = a_func_to_set_myarray(); // init the array
if (myarray != NULL && myarray[0] != 4321) // check
myarray[0] = 1234;
Now, the pointer myarray is checked for being not null, then the
contents of the array is validated. This is important, because if
you try to access an array whose address is invalid, the program
will crash and die a horrible death. But thanks to the short
circuiting, if myarray == NULL then myarray[0] won't be accessed,
and the program will work fine.evaluation order of subexpressions is not strictly defined for all operators
<?php
function a() {echo 'a';}
function b() {echo 'b';}
a() == b(); // outputs "ab", ie evaluates left-to-right
$a = 3;
var_dump( $a == $a = 4 ); // outputs bool(true), ie evaluates right-to-left
?>
this is not a bug: "we [php developers] make no guarantee about the order of evaluation".
See https://bugs.php.net/bug.php?id=61188 To jvm at jvmyers dot com:
Your first two if statements just check if there's anything in the string, if you wish to actually execute the code in your string you need eval().Regarding the ternary operator, I would rather say that the best option is to enclose all the expression in parantheses, to avoid errors and improve clarity:
<?php
print ( $a > 1 ? "many" : "just one" );
?>
PS: for php, C++, and any other language that has it.The short-circuiting IS a feature. It is also available in C, so I suppose the developers won?t remove it in future PHP versions.
It is rather nice to write:
$file=fopen("foo","r") or die("Error!");
Greets,
OliverAn easy fix (although intuitively tough to do...) is to reverse the comparison.
if (5 == $a) {}
If you forget the second '=', you'll get a parse error for trying to assign a value to a non-variable.Regarding 12345alex at gmx dot net's example:
I think you miss the identical equal documentation line from: http://php.net/manual/en/language.operators.comparison.php
$a == $b Equal TRUE if $a is equal to $b after type juggling.
$a === $b Identical TRUE if $a is equal to $b, and they are of the same type.
Try:
print array() === NULL ? "True" : "False";
Check this:
var_dump(is_null(array()));