Ausdrücke

Ausdrücke (Expressions) sind die wichtigsten Bausteine von PHP. In PHP ist fast alles, was geschrieben wird, ein Ausdruck. Die einfachste, aber auch zutreffendste Definition für einen Ausdruck ist "alles, was einen Wert hat".

Die grundlegendsten Formen von Ausdrücken sind Konstanten und Variablen. Wenn man $a = 5 schreibt, weist man $a den Ausdruck 5 zu. 5 hat offensichtlich den Wert 5. Anders ausgedrückt: 5 ist ein Ausdruck mit dem Wert 5 (in diesem Fall ist 5 eine Integer-Konstante).

Nach dieser Zuweisung würde man erwarten, dass der Wert von $a nun ebenfalls 5 ist; wenn man also $b = $a schreibt, sollte dasselbe dabei herauskommen, als hätte man $b = 5 geschrieben. Anders ausgedrückt: $a ist ebenfalls ein Ausdruck mit dem Wert 5. Wenn alles richtig funktioniert, wird genau das passieren.

Etwas kompliziertere Beispiele für Ausdrücke sind Funktionen. Betrachten wir zum Beispiel die folgende Funktion:

<?php
function foo ()
{
return
5;
}
?>

Angenommen, Sie sind mit dem Konzept von Funktionen vertraut (wenn Sie es nicht sind, lesen Sie das Kapitel über Funktionen), dann würden Sie davon ausgehen, dass die Eingabe von $c = foo() grundsätzlich dasselbe bedeutet, als würde man $c = 5 schreiben, und genau das trifft zu. Funktionen sind Ausdrücke mit dem Wert ihres Rückgabewertes. Da foo() den Wert 5 zurückgibt, ist der Wert des Ausdruckes 'foo()' 5. Normalerweise geben Funktionen nicht einfach einen statischen Wert zurück, sondern berechnen etwas.

Natürlich müssen Werte in PHP keine Integer-Zahlen sein, und oft sind sie es auch nicht. PHP unterstützt vier skalare Datentypen: int (Ganzzahlen), float (Fließkommazahlen), string (Zeichenketten) und bool (Wahrheitswerte). (Skalare sind Datentypen, die man, im Gegensatz zu zum Beispiel Arrays, nicht in kleinere Stücke 'brechen' kann.) PHP unterstützt auch zwei zusammengesetzte (nicht-skalare) Datentypen: Arrays und Objekte. Jeder dieser Datentypen kann Variablen zugewiesen und von Funktionen zurückgegeben werden.

PHP fasst den Begriff Ausdruck aber noch viel weiter, wie es auch andere Programmiersprachen tun. PHP ist eine ausdrucksorientierte Sprache, in dem Sinne, dass fast alles einen Ausdruck darstellt. Zurück zu dem Beispiel, mit dem wir uns bereits beschäftigt haben: $a = 5. Es ist einfach zu erkennen, dass hier zwei Werte enthalten sind: Der Wert der Integer-Konstanten 5 und der Wert von $a, der ebenfalls auf 5 geändert wird. In Wirklichkeit ist aber noch ein weiterer Wert enthalten, nämlich der Wert der Zuweisung selbst. Die Zuweisung selbst enthält den zugewiesenen Wert, in diesem Fall 5. In der Praxis bedeutet dies, dass $a = 5, egal was es tut, immer einen Ausdruck mit dem Wert 5 darstellt. Folglich ist $b = ($a = 5) gleichbedeutend mit $a = 5; $b = 5; (ein Semikolon markiert das Ende einer Anweisung). Da Wertzuweisungen von rechts nach links geparst werden, kann man auch $b = $a = 5 schreiben.

Ein anderes gutes Beispiel für die Ausdrucksorientierung von PHP sind Prä- und Post-Inkrement sowie die entsprechenden Dekremente. Benutzer von PHP und vielen anderen Sprachen sind vermutlich mit den Notationen variable++ und variable-- vertraut. Dies sind Inkrement- und Dekrement-Operatoren. In PHP gibt es, wie in C, zwei Arten von Inkrementen - Prä-Inkrement und Post-Inkrement. Grundsätzlich erhöhen sowohl Prä- als auch Post-Inkrement den Wert der Variable, und der Effekt auf die Variable ist derselbe. Der Unterschied liegt im Wert des Inkrement-Ausdruckes. Das Prä-Inkrement, das ++$variable geschrieben wird, enthält als Wert den Wert der erhöhten Variable (PHP erhöht den Wert der Variablen, bevor es ihren Wert ausliest, daher der Name 'PRÄ-Inkrement'). Das Post-Inkrement, das $variable++ geschrieben wird, enthält dagegen den ursprünglichen Wert von $variable vor der Erhöhung (PHP erhöht den Wert der Variablen, nachdem es ihren Wert ausgelesen hat, daher der Name 'POST-Inkrement').

Ein sehr gebräuchlicher Typ von Ausdrücken sind Vergleichsausdrücke. Diese Ausdrücke geben entweder false oder true zurück. PHP unterstützt > (größer), >= (größer oder gleich), == (gleich), != (ungleich), < (kleiner), und <= (kleiner oder gleich). Die Sprache unterstützt weiterhin ein Set von absoluten Vergleichsoperatoren: === (inhalts- und typgleich) und !== (nicht inhalts- oder typgleich). Diese Ausdrücke werden meist in bedingten Anweisungen, wie z. B. in if-Anweisungen, verwendet.

Im letzten Beispiel für Ausdrücke befassen wir uns mit kombinierten Zuweisungs- und Operator-Ausdrücken. Wir wissen bereits, dass, wenn wir $a um 1 erhöhen wollen, wir einfach $a++ oder ++$a schreiben können. Aber was tut man, wenn man den Wert um mehr als eins erhöhen will, z. B. um 3? Man könnte mehrere Male $a++ schreiben, aber das ist offensichtlich weder ein effizienter noch komfortabler Weg. Viel üblicher ist es, einfach $a = $a + 3 zu schreiben. $a + 3 gibt den Wert von $a plus 3 zurück, dieser wird wieder $a zugewiesen, was dazu führt, dass $a nun um 3 erhöht wurde. In PHP - wie in einigen anderen Programmiersprachen, z. B. in C - kann man dies aber noch kürzer schreiben, was mit der Zeit klarer wird und auch einfacher zu verstehen ist. Um 3 zu dem aktuellen Wert von $a hinzuzufügen, schreibt man $a += 3. Das bedeutet exakt: "Nimm den Wert von $a, addiere 3 hinzu und weise $a den entstandenen Wert zu". Zusätzlich dazu, dass diese Schreibweise kürzer und klarer ist, wird sie auch schneller ausgeführt. Der Wert von $a += 3 ist, wie der Wert einer regulären Zuweisung, der zugewiesene Wert. Beachten Sie, dass dieser Wert NICHT 3, sondern dem kombinierten Wert von $a plus 3 entspricht (das ist der Wert, der $a zugewiesen wird). Jeder Operator, der zwei Elemente verbindet, kann in dieser Schreibweise verwendet werden, z. B. $a -= 5 (vermindert den Wert von $a um 5) oder $b *= 7 (multipliziert den Wert von $b mit 7), usw.

Es gibt einen weiteren Ausdruck, der Ihnen vielleicht seltsam vorkommt, wenn Sie ihn bisher noch in keiner Programmiersprache kennengelernt haben, den dreifach konditionalen Operator:

<?php
$eins
? $zwei : $drei
?>

Wenn der Wert des ersten Sub-Ausdruckes (hier: $eins) true ist (d. h. nicht 0), dann wird der Wert des zweiten Subausdrucks (hier: $zwei) ausgewertet und ist das Ergebnis des konditionalen Ausdrucks. Andernfalls wird der dritte Subausdruck ausgewertet und dessen Wert zurückgegeben.

Das folgende Beispiel sollte das Verständnis von Prä- und Post-Inkrement und von Ausdrücken im Allgemeinen erleichtern:

<?php
function verdoppeln($i)
{
return
$i*2;
}
$b = $a = 5; /* Weise den Variablen $a und $b den Wert 5 zu */
$c = $a++; /* Post-Inkrement, der urspruengliche Wert von $a (5)
wird $c zugewiesen. */
$e = $d = ++$b; /* Prae-Inkrement, der erhöhte Wert von $b (6) wird $d und
$e zugewiesen. */

/* An diesem Punkt sind $d und $e beide gleich 6 */

$f = verdoppeln($d++); /* Weise $f den doppelten Wert von $d vor
der Erhöhung um eins zu, 2*6 = 12 */
$g = verdoppeln(++$e); /* Weise $g den doppelten Wert von $e nach
der Erhoehung um eins zu, 2*7 = 14 to $g */
$h = $g += 10; /* Zuerst wird $g um 10 erhöht und hat damit den Wert
24. Der Wert dieser Zuweisung (24) wird dann $h
zugewiesen, womit $h ebenfalls den Wert von 24 hat. */
?>

Einige Ausdrücke können wie Anweisungen verwendet werden. In diesem Falle hat eine Anweisung die Form 'expr ;', dies meint einen Ausdruck gefolgt von einem Semikolon. In $b = $a = 5; ist $a = 5 ein gültiger Ausdruck, aber für sich allein keine Anweisung. $b = $a = 5; ist jedoch eine gültige Anweisung.

Ein letzter Punkt, der noch zu erwähnen ist, ist der Wahrheitswert von Ausdrücken. In vielen Fällen, hauptsächlich in bedingten Anweisungen und Schleifen, ist man nicht am spezifischen Wert eines Ausdrucks interessiert, sondern kümmert sich nur darum, ob er true oder false bedeutet. Die Konstanten true und false (case-insensitiv) sind die beiden möglichen Wahrheitswerte. Wenn nötig wird ein Ausdruck automatisch in einen Booleschen Wert konvertiert. Wenn Sie mehr darüber erfahren wollen, lesen Sie den Abschnitt über Typecasting.

PHP stellt eine vollständige und mächtige Implementierung von Ausdrücken bereit, deren vollständige Dokumentation den Rahmen dieses Manuals sprengen würde. Die obigen Beispiele sollten Ihnen einen guten Eindruck davon verschaffen, was Ausdrücke sind und wie man nützliche Ausdrücke konstruieren kann. Im Rest dieses Manuals werden wir expr schreiben, um auszudrücken, dass an dieser Stelle jeder gültige PHP-Ausdruck stehen kann.

add a note

User Contributed Notes 21 notes

up
47
Magnus Deininger, dma05 at web dot de
15 years ago
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.
up
46
yasuo_ohgaki at hotmail dot com
23 years ago
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.
up
26
Mattias at mail dot ee
21 years ago
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.
up
15
chriswarbo at gmail dot com
10 years ago
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.
up
11
petruzanauticoyahoo?com!ar
16 years ago
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.
up
12
winks716
16 years ago
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~ :)
up
10
oliver at hankeln-online dot de
21 years ago
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
up
7
egonfreeman at gmail dot com
17 years ago
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)
up
4
denzoo at gmail dot com
16 years ago
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().
up
5
shawnster
17 years ago
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.
up
1
Bichis Paul
7 years ago
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()));
up
2
anthony at n dot o dot s dot p dot a dot m dot trams dot com
23 years ago
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' ) ;
up
0
antickon at gmail dot com
12 years ago
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
up
-2
richard at phase4 dot ie
18 years ago
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.
up
-4
jvm at jvmyers dot com
16 years ago
<?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!
up
-3
Anonymous
18 years ago
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.
up
-4
tom at darlingpet dot com
19 years ago
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.
up
-6
nabil_kadimi at hotmail dot com
17 years ago
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
?>
up
-10
george dot langley at shaw dot ca
16 years ago
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
up
-12
12345alex at gmx dot net
18 years ago
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
up
-18
Martin K
18 years ago
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.
To Top