|
Chapter 5. ExpressionsExpressions are the most important building stones of PHP. In PHP, almost anything you write is an expression. The simplest yet most accurate way to define an expression is "anything that has a value". The most basic forms of expressions are constants and variables. When you type "$a = 5", you're assigning '5' into $a. '5', obviously, has the value 5, or in other words '5' is an expression with the value of 5 (in this case, '5' is an integer constant). After this assignment, you'd expect $a's value to be 5 as well, so if you wrote $b = $a, you'd expect it to behave just as if you wrote $b = 5. In other words, $a is an expression with the value of 5 as well. If everything works right, this is exactly what will happen. Slightly more complex examples for expressions are functions. For instance, consider the following function: <?php
Assuming you're familiar with the concept of functions (if you're
not, take a look at the chapter about functions), you'd assume
that typing Of course, values in PHP don't have to be integers, and very often they aren't. PHP supports four scalar value types: integer values, floating point values (float), string values and boolean values (scalar values are values that you can't 'break' into smaller pieces, unlike arrays, for instance). PHP also supports two composite (non-scalar) types: arrays and objects. Each of these value types can be assigned into variables or returned from functions. PHP takes expressions much further, in the same way many other languages do. PHP is an expression-oriented language, in the sense that almost everything is an expression. Consider the example we've already dealt with, '$a = 5'. It's easy to see that there are two values involved here, the value of the integer constant '5', and the value of $a which is being updated to 5 as well. But the truth is that there's one additional value involved here, and that's the value of the assignment itself. The assignment itself evaluates to the assigned value, in this case 5. In practice, it means that '$a = 5', regardless of what it does, is an expression with the value 5. Thus, writing something like '$b = ($a = 5)' is like writing '$a = 5; $b = 5;' (a semicolon marks the end of a statement). Since assignments are parsed in a right to left order, you can also write '$b = $a = 5'. Another good example of expression orientation is pre- and post-increment and decrement. Users of PHP and many other languages may be familiar with the notation of variable++ and variable--. These are increment and decrement operators. In PHP/FI 2, the statement '$a++' has no value (is not an expression), and thus you can't assign it or use it in any way. PHP enhances the increment/decrement capabilities by making these expressions as well, like in C. In PHP, like in C, there are two types of increment - pre-increment and post-increment. Both pre-increment and post-increment essentially increment the variable, and the effect on the variable is identical. The difference is with the value of the increment expression. Pre-increment, which is written '++$variable', evaluates to the incremented value (PHP increments the variable before reading its value, thus the name 'pre-increment'). Post-increment, which is written '$variable++' evaluates to the original value of $variable, before it was incremented (PHP increments the variable after reading its value, thus the name 'post-increment').
A very common type of expressions are comparison
expressions. These expressions evaluate to either The last example of expressions we'll deal with here is combined operator-assignment expressions. You already know that if you want to increment $a by 1, you can simply write '$a++' or '++$a'. But what if you want to add more than one to it, for instance 3? You could write '$a++' multiple times, but this is obviously not a very efficient or comfortable way. A much more common practice is to write '$a = $a + 3'. '$a + 3' evaluates to the value of $a plus 3, and is assigned back into $a, which results in incrementing $a by 3. In PHP, as in several other languages like C, you can write this in a shorter way, which with time would become clearer and quicker to understand as well. Adding 3 to the current value of $a can be written '$a += 3'. This means exactly "take the value of $a, add 3 to it, and assign it back into $a". In addition to being shorter and clearer, this also results in faster execution. The value of '$a += 3', like the value of a regular assignment, is the assigned value. Notice that it is NOT 3, but the combined value of $a plus 3 (this is the value that's assigned into $a). Any two-place operator can be used in this operator-assignment mode, for example '$a -= 5' (subtract 5 from the value of $a), '$b *= 7' (multiply the value of $b by 7), etc. There is one more expression that may seem odd if you haven't seen it in other languages, the ternary conditional operator: <?php
If the value of the first subexpression is The following example should help you understand pre- and post-increment and expressions in general a bit better: <?php Some expressions can be considered as statements. In this case, a statement has the form of 'expr' ';' that is, an expression followed by a semicolon. In '$b=$a=5;', $a=5 is a valid expression, but it's not a statement by itself. '$b=$a=5;' however is a valid statement.
One last thing worth mentioning is the truth value of expressions.
In many events, mainly in conditional execution and loops, you're
not interested in the specific value of the expression, but only
care about whether it means
PHP provides a full and powerful implementation of expressions, and
documenting it entirely goes beyond the scope of this manual. The
above examples should give you a good idea about what expressions
are and how you can construct useful expressions. Throughout the
rest of this manual we'll write Related Examples ( Source code ) » language.expressions Examples ( Source code ) » Clean Path by Regular Expressions Examples ( Source code ) » Email validation with Regular Expressions Examples ( Source code ) » String replace with Regular Expressions Examples ( Source code ) » For loop format Code Examples / Notes » language.expressions12345alex
this code: print array() == NULL ? "True" : "False"; print " (" . (array() == NULL) . ")\n"; $arr = array(); print array() == $arr ? "True" : "False"; print " (" . (array() == $arr) . ")\n"; print count(array()) . "\n"; print count(NULL) . "\n"; will output (on php4 and php5): True (1) True (1) 0 0 so to decide wether i have NULL or an empty array i will also have to use gettype(). this seems some kind of weird for me, although if is this is a bug, somebody should have noticed it before. alex anthony
The ternary conditional operator is a useful way of avoiding inconvenient if statements. They can even be used in the middle of a string concatenation, if you use parentheses. Example: if ( $wakka ) { $string = 'foo' ; } else { $string = 'bar' ; } The above can be expressed like the following: $string = $wakka ? 'foo' : 'bar' ; If $wakka is true, $string is assigned 'foo', and if it's false, $string is assigned 'bar'. To do the same in a concatenation, try: $string = $otherString . ( $wakka ? 'foo' : 'bar' ) ; oliver
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, Oliver stian
The short-circuit feature is indeed intended, and there are two types of evaluators, those who DO short-circuit, and those who DON'T, || / && and | / & respectively. The latter method is the bitwise operators, but works great with the usual boolean values ( 0/1 ) So if you don't want short-circuiting, try using the | and & instead. Read more about the bitwise operators here: http://www.php.net/manual/en/language.operators.bitwise.php tom
Something I've noticed with ternary expressions is if you do something like : <?= $var=="something" ? "is something" : "not something"; ?> It will give wacky results sometimes... So be sure to enclose the ternary expression in parenthesis when ever necessary (such as having multiple expressions or nested ternary expressions) The above could look like: <?= ($var=="something") ? "is something" : "not something"; ?> It's also a good idea to use parenthesis when using something SIMILAR to: <?php echo (trim($var)=="") ? "empty" : "not empty"; ?> In some cases other than the <?= ?> example, not placing the entire expression in appropriate parenthesis might yield undesirable results as well.. but I'm not quite sure. winks716
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~ :) petruzanauticoyahoo?com!ar
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. sabinx
Pre- and Post-Incrementation, I believe, are important to note and in the correct place. The section deals with the value of an expression. ++$a and $a++ have different values, and both forms have valid uses. And, because it can be confusing, it is that much more important to note. Although it could be worded better, it does belong. yasuo_ohgaki
Manual defines "expression is anything that has value", Therefore, parser will give error for following code. ($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, ($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. php
It should probably be mentioned that the short-circuiting of expressions (mentioned in some of the comments above) is often called "lazy evaluation" (in case someone else searches for the term "lazy" on this page and comes up empty!).
egonfreeman
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) 31-may-2005 08:07
I don't see why it is necessary here to explain pre- and post- incrementing. This is something that will confuse new users of PHP, even longer time programmers will sometimes miss a the fine details of a construct like that. If something has a side-effect it should be on a line of it's own, or at least be an expression of it's own and not part of an assignment, condition or whatever. george dot langley
Here's a quick example of Pre and Post-incrementation, in case anyone does feel confused (ref anonymous poster 31 May 2005) <?PHP echo "Using Pre-increment ++\$a: "; $a = 1; echo "\$a = $a "; $b = ++$a; echo "\$b = ++\$a, so \$b = $b and \$a = $a "; echo " "; echo "Using Post-increment \$a++: "; $a = 1; echo "\$a = $a "; $b = $a++; echo "\$b = \$a++, so \$b = $b and \$a = $a "; ?> HTH richard
Follow up on Martin K. There are no hard and fast rules regarding operator precedence. Newbies should definitely learn them, but if their use results in code that is not easy to read you should use parentheses. The two important things are that it works properly AND is maintainable by you and others.
nabil_kadimi
Attention! php will not warn you if you write (1) When you mean (2) (1) <? if($a=0) echo "condition is true"; else echo "condition is false"; //output: condition is false ?> (2) <? if($a==0) echo "condition is true"; else echo "condition is false"; //output: condition is true ?> martin k
At 04-Feb-2005 05:13, tom at darlingpet dot com said: > It's also a good idea to use parenthesis when using something SIMILAR to: > > <?php > echo (trim($var)=="") ? "empty" : "not empty"; > ?> No, it's a BAD idea. All the short-circuiting operators, including the ternary conditional operator, have LOWER precedence than the comparison operators, so they almost NEVER need parentheses around their subexpressions. Inserting the parentheses suggested above does not change the meaning of the code, but their use misleads inexperienced programmers to expect that things like this will work in a similar manner: <?php function my_print($a) { print($a); } my_print (trim($var)=="") ? "empty" : "not empty"; ?> when of course it doesn't. Rather than worrying that code doesn't work as expected, simply learn the precedence rules (http://www.php.net/manual/en/language.operators.php) so that one expects the right things. shawnster
An 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. mattias
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. stochnagara
12345alex at gmx dot net 's case is actually handled by the === operator. That's what he needs. There is also another widely used function. I call it myself is_nil which is true for NULL,FALSE,array() and '', but not for 0 and "0". function is_nil ($value) { return !$value && $value !== 0 && $value !== '0'; } Another useful function is "get first argument if it is not empty or get second argument otherwise". The code is: function def ($value, $defaultValue) { return is_nil ($value) ? $defaultValue : $value; } 27-apr-2005 03:40
($bb || !$bb) ....2 Be or not 2 to be thats the question ;-) |