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.
Expresiones
La expresiones son las piedras de construcción más importantes de PHP. En PHP casi todo lo que se escribe es una expresión. La manera más simple y acertada de definir lo que es una expresión es "cualquier cosa que tiene un valor".
Las formas más básicas de expresiones son las constantes y las variables. Cuando se escribe "$a = 5", se está asignando '5' a $a. '5', obviamente, tiene el valor 5, o en otras palabras, '5' es una expresión con el valor de 5 (en este caso, '5' es una constante entera).
Después de esta asignación, se espera que el valor de $a sea 5 también, por lo que si se escribe $b = $a, se espera que esto se comporte tal como si se escribiera $b = 5. En otras palabras, $a es también una expresión con el valor 5. Si todo funciona bien, esto es exactamente lo que sucederá.
Un ejemplo de expresiones algo más complejo son las funciones. Por ejemplo, considere la siguiente función:
<?php
function foo ()
{
return 5;
}
?>
Asumiendo que está familiarizado con el concepto de función (si no lo está, échele una ojeada al capÃtulo sobre funciones), asumirá que escribir $c = foo() es esencialmente igual que escribir $c = 5. Y está en lo cierto. Las funciones son expresiones con el valor de sus valores devueltos. Ya que foo() devuelve 5, el valor de la expresión 'foo()' es 5. Normalmente las funciones no sólo devuelven un valor estático, sino que computan algo.
Por supuesto, los valores en PHP no tienen que ser enteros, y con frecuencia no lo son. PHP soporta cuatro tipos de valores escalares: valores enteros (integer), valores de coma (punto) flotante (float), valores de cadena (string) y valores booleanos (boolean) - (valores escalares son aquellos que no se pueden descomponer en piezas más pequeñas, a diferencia de las matrices, por ejemplo). PHP también soporta dos tipos compuestos (no escalares): matrices (arrays) y objetos. Cada uno de estos tipos de valores pueden ser asignados a variables o devueltos desde funciones.
PHP lleva las expresiones mucho más allá, de la misma manera que lo hacen otros lenguajes. PHP es un lenguaje orientado a expresiones, en el sentido de que casi todo es una expresión. Considere el ejemplo que ya hemos tratado, '$a = 5'. Es fácil de ver que aquà hay dos valores involucrados, el valor de la constante entera '5', y el valor de $a que ha sido actualizado a 5 también. Aunque la verdad es que existe aquà un valor adicional involucrado, que es el valor de la asignación misma. La asignación evalúa al valor asignado, en este caso 5. En la práctica, esto significa que '$a = 5', sin importar lo que haga, es una expresión con el valor 5. De este modo, escribir algo como '$b = ($a = 5)' es igual que escribir '$a = 5; $b = 5;' (el punto y coma marca el final de una sentencia). Ya que las asignaciones se analizan de derecha a izquierda, también se puede escribir '$b = $a = 5'.
Otro buen ejemplo de orientación a expresiones es el pre- y post-incremento y decremento. Los usuarios de PHP y de otros muchos lenguajes pueden estar familiarizados con la notación variable++ y variable--. Éstos son los operadores de incremento y decremento. En PHP, al igual que en C, hay dos tipos de incrementos - pre-incremento y post-incremento. Ambos esencialmente incrementan la variable, y el efecto sobre la variable es idéntico. La diferencia está con el valor de la expresión de incremento. Pre-incremento, que se escribre '++$variable', evalúa al valor incrementado (PHP incrementa la variable antes de leer su valor, de ahà el nombre de 'pre-incremento'). Post-incremento, que se escribe '$variable++' evalúa el valor original de $variable, antes de que sea incrementado (PHP incrementa la variable después de leer su valor, de ahà el nombre de 'post-incremento').
Un tipo de expresiones muy comunes son las expresiones de comparación.
Estas expresiones evalúan si algo es FALSE (falso) o TRUE (verdadero). PHP
soporta > (mayor que), >= (mayor o igual que), == (igual),
!= (distinto), < (menor que) y <= (menor o igual que).
El lenguaje también soporta un conjunto de operadores de equivalencia estricta: ===
(igual y del mismo tipo) y !== (diferente o de distinto tipo).
Estas expresiones se usan mayormente dentro de ejecuciones condicionales,
tales como la sentencia if.
El último ejemplo de expresiones que trataremos aquà es una combinación de expresiones operador-asignación. Ya sabe que si quiere incrementar $a en 1, puede simplemente escribir '$a++' o '++$a'. Pero si lo que quiere es añadirle más de uno, por ejemplo 3, podrÃa escribir '$a++' varias veces, pero esto, obviamente, no es una manera muy eficiente o cómoda. Una práctica mucho más común es escribir '$a = $a + 3'. '$a + 3' evalúa al valor de $a más 3, y se vuelve a asignar a $a, lo que resulta en incrementar $a en 3. En PHP, como en otros lenguajes como C, se puede escribir esto de una manera más abreviada, lo que con el tiempo se podrÃa convertir en una forma más clara y rápida de entenderlo. Añadir 3 al valor actual de $a puede ser escrito '$a += 3'. Esto significa exactamente "toma el valor de $a, añádele 3 y asÃgnalo de nuevo a $a". Además de ser más corto y claro, también resulta en una ejecución más rápida. El valor de '$a += 3', al igual que el valor de una asignación normal, es el valor asignado. Observe que NO es 3, sino el valor combinado de $a más 3 (éste es el valor que es asignado a $a). Se puede usar cualquier operador compuesto de dos partes en este modo de operador-asignación, por ejemplo '$a -= 5' (restar 5 del valor de $a), '$b *= 7' (multiplicar el valor de $b por 7), etc.
Existe una expresión más que le puede parecer rara si no la ha visto en otros lenguajes, el operador condicional ternario:
<?php
$primero ? $segundo : $tercero
?>
Si el valor de la primera subexpresión es TRUE (no es cero),
se evalúa la segunda subexpresión, y ése será el resultado de
la expresión condicional. Si no, se evalúa la tercera
subexpresión, y ése será el valor.
El siguiente ejemplo deberÃa ayudarle a comprender un poco mejor el pre- y post-incremento y las expresiones en general:
<?php
function doble($i)
{
return $i*2;
}
$b = $a = 5; /* asignar el valor cinco a la variable $a y $b */
$c = $a++; /* post-incremento, asignar el valor original de $a
(5) a $c */
$e = $d = ++$b; /* pre-incremento, asignar el valor incrementado de
$b (6) a $d y $e */
/* en este punto, $d y $e son iguales a 6 */
$f = doble($d++); /* asignar el doble del valor de $d antes
del incremento, 2*6 = 12, a $f */
$g = doble(++$e); /* asignar el doble del valor de $e después
del incremento, 2*7 = 14, a $g */
$h = $g += 10; /* primero, $g es incrementado en 10 y finaliza con el
valor 24. El valor de la asignación (24) es
asignado después a $h, y $h finaliza también con el
valor 24. */
?>
Algunas expresiones pueden considerarse como sentencias. En este caso, una sentencia tiene la forma 'expr ;', es decir, una expresión seguida de un punto y coma. En '$b = $a = 5;', '$a = 5' es una expresión válida, pero no es una sentencia en sÃ. Sin embargo, '$b = $a = 5;' es una sentencia válida.
Lo último que vale la pena mencionar es el valor verdadero de las expresiones.
En muchos casos, principalmente en ejecuciones condicionales y bucles, no
interesa saber el valor especÃfico de la expresión, sino sólo
si el valor significa TRUE o FALSE.
Las constantes TRUE y FALSE (insensible a mayúsculas-minúsculas) son los
dos valores booleanos posibles. Cuando es necesario, una expresión es
convertida automáticamente al tipo boolean. Véase la
sección sobre
conversión de tipos para más detalles.
PHP proporciona una implementación completa y potente de expresiones, y documentarla por completo va más allá del ámbito de este manual. Los ejemplos de arriba deberÃan darle una buena idea de lo que son las expresiones y cómo construir expresiones útiles. Durante el resto de este manual se escribirá expr para indicar cualquier expresión de PHP válida.
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.
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' ) ;
<?php
// Compound booleans expressed as string args in an 'if' statement don't work as expected:
//
// Context:
// 1. I generate an array of counters
// 2. I dynamically generate a compound boolean based on selected counters in the array
// Note: since the real array is sparse, I must use the 'empty' operator
// 3. When I submit the compound boolean as the expression of an 'if' statement,
// the 'if' appears to resolve ONLY the first element of the compound boolean.
// Conclusion: appears to be a short-circuiting issue
$aArray = array(1,0);
// Case 1: 'if' expression passed as string:
$sCondition = "!empty($aArray[0]) && !empty($aArray[1])";
if ($sCondition)
{
echo "1. Conditions met<br />";
}
else
{
echo "1. Conditions not met<br />";
}
// Case 1 output: "1. Conditions met"
// Case 2: same as Case 1, but using catenation operator
if ("".$sCondition."")
{
echo "2. Conditions met<br />";
}
else
{
echo "2. Conditions not met<br />";
}
// Case 2 output: "2. Conditions met"
// Case 3: same 'if' expression but passed in context:
if (!empty($aArray[0]) && !empty($aArray[1]))
{
echo "3. Conditions met<br />";
}
else
{
echo "3. Conditions not met<br />";
}
// Case 3 output: "3. Conditions not met"
// jvm@jvmyers.com
?>
PS: the bug folks say this "does not imply a bug in PHP itself." Sure bugs me!
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.
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
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:<br>";
$a = 1;
echo "\$a = $a<br>";
$b = ++$a;
echo "\$b = ++\$a, so \$b = $b and \$a = $a<br>";
echo "<br>";
echo "Using Post-increment \$a++:<br>";
$a = 1;
echo "\$a = $a<br>";
$b = $a++;
echo "\$b = \$a++, so \$b = $b and \$a = $a<br>";
?>
HTH
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
?>
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.
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
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.
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
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)
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.
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.
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.
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!).
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.
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().
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;
}
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.
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
The ternary operator is a convenient way to conditionally return an expression. 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' ) ;
