2.4. Expressions and Operators

An
expression is a bit of PHP that can be
evaluated to produce a value. The simplest expressions are literal
values and variables. A literal value evaluates to itself, while a
variable evaluates to the value stored in the variable. More complex
expressions can be formed using simple expressions and operators.

An operator takes some values (the
operands) and does
something (for instance, adds them together). Operators are written
as punctuation symbols—for instance, the +
and - familiar to us from math. Some operators
modify their operands, while most do not.

Table 2-3 summarizes the
operators in PHP, many of which were
borrowed from C and Perl. The column labeled
"P" gives the
operator's precedence; the operators are listed in
precedence order, from highest to lowest. The column labeled
"A" gives the
operator's associativity, which can be L
(left-to-right), R (right-to-left), or N (non-associative).

Table 2-3. PHP operators

P

A

Operator

Operation

19

N

new

Create new object

18

R

[

Array subscript

17

R

!

Logical NOT

R

~

Bitwise NOT

R

++

Increment

R

--

Decrement

R

(int), (double),
(string), (array),
(object)

Cast

R

@

Inhibit errors

16

L

*

Multiplication

L

/

Division

L

%

Modulus

15

L

+

Addition

L

-

Subtraction

L

.

String concatenation

14

L

<<

Bitwise shift left

L

>>

Bitwise shift right

13

N

<, <=

Less than, less than or equal

N

>, >=

Greater than, greater than or equal

12

N

==

Value equality

N

!=, <>

Inequality

N

===

Type and value equality

N

!==

Type and value inequality

11

L

&

Bitwise AND

10

L

^

Bitwise XOR

9

L

|

Bitwise OR

8

L

&&

Logical AND

7

L

||

Logical OR

6

L

?:

Conditional operator

5

L

=

Assignment

L

+=, -=, *=,
/=, .=, %=,
&=, |=,
^=, ~=,
<<=, >>=

Assignment with operation

4

L

and

Logical AND

3

L

xor

Logical XOR

2

L

or

Logical OR

1

L

,

List separator

2.4.1. Number of Operands

Most operators in PHP are
binary
operators; they combine two operands (or expressions) into a single,
more complex expression. PHP also supports a number of
unary
operators, which convert a single expression into a more complex
expression. Finally, PHP supports a single
ternary
operator that combines three expressions into a single expression.

2.4.2. Operator Precedence

The order in which operators in an
expression are evaluated depends on their relative precedence. For
example, you might write:

2 + 4 * 3

As you can see in Table 2-3, the addition and
multiplication operators have different precedence, with
multiplication higher than addition. So the multiplication happens
before the addition, giving 2+12, or 14, as the answer. If
the precedence of addition and multiplication were reversed,
6*3, or
18, would be the answer.

To force a particular
order, you can group operands with the appropriate operator in
parentheses. In our previous example, to get the value
18, you can use this expression:

(2 + 4) * 3

It is possible to write all complex expressions (expressions
containing more than a single operator) simply by putting the
operands and operators in the appropriate order so that their
relative precedence yields the answer you want. Most programmers,
however, write the operators in the order that they feel makes the
most sense to programmers, and add parentheses to ensure it makes
sense to PHP as well. Getting precedence wrong leads to code like:

$x + 2 / $y >= 4 ? $z : $x << $z

This code is hard to read and is almost definitely not doing what the
programmer expected it to do.

One way many programmers deal with the complex
precedence rules in
programming languages is to reduce precedence down to two rules:

Multiplication and division have higher precedence than addition and
subtraction.

Use parentheses for anything else.

2.4.3. Operator Associativity

Associativity defines the order in which
operators with the same order of precedence are evaluated. For example,
look at:

2 / 2 * 2

The division and multiplication operators have the same precedence,
but the result of the expression depends on which operation we do
first:

2/(2*2) // 0.5
(2/2)*2 // 2

The division and multiplication operators are left-associative; this
means that in cases of ambiguity, the operators are evaluated from
left to right. In this example, the correct result is 2.

2.4.4. Implicit Casting

Many
operators have expectations of their operands—for instance,
binary math operators typically require both operands to be of the
same type. PHP's variables can store integers,
floating-point numbers, strings, and more, and to keep as much of the
type details away from the programmer as possible, PHP converts
values from one type to another as necessary.

The conversion of a value from one type to
another is called casting. This kind of
implicit casting is called type juggling in
PHP. The rules for the type juggling done by
arithmetic operators are shown in Table 2-4.

Table 2-4. Implicit casting rules for binary arithmetic operations

Type of first operand

Type of second operand

Conversion performed

Integer

Floating point

The integer is converted to a floating-point number

Integer

String

The string is converted to a number; if the value after conversion is
a floating-point number, the integer is converted to a floating-point
number

Floating point

String

The string is converted to a floating-point number

Some
other operators have different expectations of their operands, and
thus have different rules. For example, the string concatenation
operator converts both operands to strings before concatenating them:

3 . 2.74 // gives the string 32.74

You can use a string anywhere PHP
expects a number. The string is presumed to start with an integer or
floating-point number. If no number is found at the start of the
string, the numeric value of that string is 0. If the string contains
a period (.) or upper- or lowercase
e, evaluating it numerically produces a
floating-point number. For example:

2.4.5. Arithmetic Operators

The arithmetic
operators are operators you'll recognize from
everyday use. Most of the arithmetic operators are binary; however,
the arithmetic negation and arithmetic assertion operators are unary.
These operators require numeric values, and non-numeric values are
converted into numeric values by the rules described in Section 2.4.11. The arithmetic operators are:

Addition (+)

The result of the addition operator is the sum of the two
operands.

Subtraction (-)

The result of the subtraction operator is the difference
between the two operands; i.e., the value of the second operand
subtracted from the first.

Multiplication (*)

The result of the multiplication operator is the
product of the two operands. For example, 3*4 is 12.

Division (/)

The result of the division operator is the quotient of
the two operands. Dividing two integers can give an integer (e.g.,
4/2) or a floating-point result (e.g.,
1/2).

Modulus (%)

The modulus
operator converts both operands to integers and returns the remainder
of the division of the first operand by the second operand. For
example, 10%6 is 4.

Arithmetic negation (-)

The arithmetic negation operator returns the
operand multiplied by -1, effectively changing its sign. For example,
-(3-4)
evaluates to 1. Arithmetic negation is different
from the subtraction operator, even though they both are written as a
minus sign. Arithmetic negation is always unary and before the operand.
Subtraction is binary and between its operands.

Arithmetic assertion (+)

The arithmetic assertion operator returns
the operand multiplied by +1, which has no effect. It is used only as
a visual cue to indicate the sign of a value. For example,
+(3-4)
evaluates to -1, just as (3-4) does.

2.4.6. String Concatenation Operator

Manipulating
strings is such a core part of
PHP applications that PHP has a separate string concatenation
operator (.). The concatenation operator appends
the righthand operand to the lefthand operand and returns the
resulting string. Operands are first converted to strings, if
necessary. For example:

2.4.7. Autoincrement and Autodecrement Operators

In programming,
one of the most common
operations is to increase or decrease the value of a variable by one.
The unary autoincrement (++) and autodecrement
(--) operators provide shortcuts for these common
operations. These operators are unique in that they work only on
variables; the operators change their operands'
values as well as returning a value.

There are two ways to use autoincrement or autodecrement in
expressions. If you put
the operator in front of the operand, it returns the new value of the
operand (incremented or decremented). If you put the operator after
the operand, it returns the original value of the operand (before the
increment or decrement). Table 2-5 lists the
different operations.

Table 2-5. Autoincrement and autodecrement operations

Operator

Name

Value returned

Effect on $var

$var++

Post-increment

$var

Incremented

++$var

Pre-increment

$var + 1

Incremented

$var--

Post-decrement

$var

Decremented

--$var

Pre-decrement

$var - 1

Decremented

These operators can be applied to
strings
as well as numbers. Incrementing an alphabetic character turns it
into the next letter in the alphabet. As illustrated in Table 2-6, incrementing "z" or
"Z" wraps it back to "a" or
"Z" and increments the previous character by one,
as though the characters were in a base-26 number system.

Table 2-6. Autoincrement with letters

Incrementing this

Gives this

"a"

"b"

"z"

"aa"

"spaz"

"spba"

"K9"

"L0"

"42"

"43"

2.4.8. Comparison Operators

As their name suggests, comparison
operators compare operands. The result is always either
true, if the comparison is truthful, or
false, otherwise.

Operands to the comparison operators can be both numeric, both
string,
or one numeric and one string. The operators check for truthfulness
in slightly different ways based on the types and values of the
operands, either using strictly numeric comparisons or using
lexicographic (textual) comparisons. Table 2-7
outlines when each type of check is used.

Table 2-7. Type of comparision performed by the comparision operators

First operand

Second operand

Comparison

Number

Number

Numeric

String that is entirely numeric

String that is entirely numeric

Numeric

String that is entirely numeric

Number

Numeric

String that is not entirely numeric

Number

Lexicographic

String that is entirely numeric

String that is not entirely numeric

Lexicographic

String that is not entirely numeric

String that is not entirely numeric

Lexicographic

One important thing to note is that two numeric strings are compared
as if they were numbers. If you have two strings that consist
entirely of numeric characters and you need to compare them
lexicographically, use the strcmp(
) function.

The comparison operators are:

Equality (==)

If both operands are equal, this operator returns
true; otherwise, it returns
false.

Identical (===)

If both operands are equal and are of the same type, this operator
returns true; otherwise, it returns
false. Note that this operator does
not do implicit type casting. This operator is
useful when you don't know if the values
you're comparing are of the same type. Simple
comparison may involve value conversion. For instance, the strings
"0.0" and "0" are not equal.
The == operator says they are, but
=== says they are not.

Inequality (!= or <>)

If both operands are not equal, this operator returns
true; otherwise, it returns
false.

Not identical (!==)

If both operands are not equal, or they are not of the same type,
this operator returns true; otherwise, it returns
false.

Greater than (>)

If the lefthand operator is greater than the righthand operator, this
operator returns true; otherwise, it returns
false.

Greater than or equal to (>=)

If the lefthand operator is greater than or equal to the righthand
operator, this operator returns true; otherwise,
it returns false.

Less than (<)

If the lefthand operator is less than the righthand operator, this
operator returns true; otherwise, it returns
false.

Less than or equal to (<=)

If the lefthand operator is less than or equal to the righthand
operator, this operator returns true; otherwise,
it returns false.

2.4.9. Bitwise Operators

The bitwise
operators act on the binary representation of their operands. Each
operand is first turned into a binary representation of the value, as
described in the bitwise negation operator entry in the following
list. All the bitwise operators work on numbers as well as strings,
but they vary in their treatment of string operands of different
lengths. The bitwise operators are:

Bitwise negation (~)

The bitwise negation operator changes 1s to 0s and 0s to 1s in the
binary representations of the operands. Floating-point values are
converted to integers before the operation takes place. If the
operand is a string, the resulting value is a string the same length
as the original, with each character in the string negated.

Bitwise AND (&)

The bitwise AND operator compares each corresponding bit in the
binary representations of the operands. If both bits are 1, the
corresponding bit in the result is 1; otherwise, the corresponding
bit is 0. For example, 0755&0671 is
0651. This is a bit easier to understand if we
look at the binary representation. Octal 0755 is binary 111101101,
and octal 0671 is binary 110111001. We can the easily see which bits
are on in both numbers and visually come up with the answer:

111101101
& 110111001
---------
110101001

The binary number 110101001 is octal 0651.[2] You can use the PHP
functions bindec( ), decbin( ),
octdec( ), and decoct( ) to
convert numbers back and forth when you are trying to understand
binary arithmetic.

[2]Here's a tip: split the binary number up into
three groups. 6 is binary 110, 5 is binary 101, and 1 is binary 001;
thus, 0651 is 110101001.

If both operands are strings, the operator returns a string in which
each character is the result of a bitwise AND operation between the
two corresponding characters in the operands. The resulting string is
the length of the shorter of the two operands; trailing extra
characters in the longer string are ignored. For example,
"wolf"&"cat" is "cad".

Bitwise OR (|)

The bitwise OR operator compares each corresponding bit in the binary
representations of the operands. If both bits are 0, the resulting
bit is 0; otherwise, the resulting bit is 1. For example,
0755|020
is 0775.

If both operands are strings, the operator returns a string in which
each character is the result of a bitwise OR operation between the
two corresponding characters in the operands. The resulting string is
the length of the longer of the two operands, and the shorter string
is padded at the end with binary 0s. For example,
"pussy"|"cat" is "suwsy".

Bitwise XOR (^)

The bitwise XOR operator compares each corresponding bit in the
binary representation of the operands. If either of the bits in the
pair, but not both, is 1, the resulting bit is 1; otherwise, the
resulting bit is 0. For example, 0755^023 is
776.

If both operands are strings, this operator returns a string in which
each character is the result of a bitwise XOR operation between the
two corresponding characters in the operands. If the two strings are
different lengths, the resulting string is the length of the shorter
operand, and extra trailing characters in the longer string are
ignored. For example, "big drink"^"AA" is
"#(".

Left shift (<<)

The left shift operator shifts the bits in the binary representation
of the lefthand operand left by the number of places given in the
righthand operand. Both operands will be converted to integers if
they aren't already. Shifting a binary number to the
left inserts a 0 as the rightmost bit of the number and moves all
other bits to the left one place. For example, 3<<1 (or binary 11
shifted one place left) results in 6 (binary 110).

Note that each place to the left that a number is shifted results in
a doubling of the number. The result of left shifting is multiplying
the lefthand operand by 2 to the power of the righthand operand.

Right shift (>>)

The right shift operator shifts the bits in the binary representation
of the lefthand operand right by the number of places given in the
righthand operand. Both operands will be converted to integers if
they aren't already. Shifting a binary number to the
right inserts a 0 as the leftmost bit of the number and moves all
other bits to the right one place. The rightmost bit is discarded.
For example, 13>>1 (or binary 1101) shifted one place right results
in 6 (binary 110).

2.4.10. Logical Operators

Logical
operators provide ways for you to build complex logical expressions.
Logical operators treat their operands as Boolean values and return a
Boolean value. There are both punctuation and English versions of the
operators (|| and or are the
same operator). The logical operators are:

Logical AND (&&, and)

The result of the logical AND operation is true if
and only if both operands are true; otherwise, it
is false. If the value of the first operand is
false, the logical AND operator knows that the
resulting value must also be false, so the
righthand operand is never evaluated. This process is called
short-circuiting, and a common PHP idiom uses
it to ensure that a piece of code is evaluated only if something is
true. For example, you might connect to a database only if some flag
is not false:

$result = $flag and mysql_connect( );

The && and and
operators differ only in their precedence.

Logical OR (||, or)

The result of the logical OR operation is true if
either operand is true; otherwise, the result is
false. Like the logical AND operator, the logical
OR operator is short-circuited. If the lefthand operator is
true, the result of the operator must be
true, so the righthand operator is never
evaluated. A common PHP idiom uses this to trigger an error condition
if something goes wrong. For example:

$result = fopen($filename) or exit( );

The || and or operators differ
only in their precedence.

Logical XOR (xor)

The result of the logical XOR operation is true if
either operand, but not both, is true; otherwise,
it is false.

Logical negation (!)

The logical negation operator returns the Boolean value
true if the operand evaluates to
false, and false if the operand
evaluates to true.

2.4.11. Casting Operators

Although
PHP is a weakly typed
language, there are occasions when it's useful to
consider a value as a specific type. The casting operators,
(int), (float),
(string), (bool),
(array), and (object), allow
you to force a value into a particular type. To use a casting
operator, put the operator to the left of the operand. Table 2-8 lists the casting operators, synonymous
operands, and the type to which the operator changes the value.

Table 2-8. PHP casting operators

Operator

Synonymous operators

Changes type to

(int)

(integer)

Integer

(float)

(real)

Floating point

(string)

String

(bool)

(boolean)

Boolean

(array)

Array

(object)

Object

Casting affects the way other operators interpret a value, rather
than changing the value in a variable. For example, the code:

$a = "5";
$b = (int) $a;

assigns $b the integer value of
$a; $a remains the string
"5". To cast the value of the variable itself, you
must assign the result of a cast back into the variable:

$a = "5"
$a = (int) $a; // now $a holds an integer

Not every cast is useful: casting an array to a numeric type gives
1, and casting an array to a string gives
"Array" (seeing this in your output is a sure sign
that you've printed a variable that contains an
array).

Casting an object to an array builds an array of
the properties, mapping property names to values:

Keys that aren't valid identifiers, and thus are
invalid property names, are inaccessible but are restored when the
object is cast back to an array.

2.4.12. Assignment Operators

Assignment
operators store or update values in variables. The autoincrement and
autodecrement operators we saw earlier are highly specialized
assignment operators—here we see the more general forms. The
basic assignment operator is =, but we'll also see
combinations of assignment and binary operations, such as += and
&=.

2.4.12.1. Assignment

The basic assignment operator (=) assigns
a value to a variable. The lefthand operand is always a variable. The
righthand operand can be any expression—any simple literal,
variable, or complex expression. The righthand
operand's value is stored in the variable named by
the lefthand operand.

Because all operators are required to return a value, the assignment
operator returns the value assigned to the variable. For example, the
expression $a = 5 not only assigns 5 to $a, but also behaves as the
value 5 if used in a larger expression. Consider the following
expressions:

$a = 5;
$b = 10;
$c = ($a = $b);

The expression $a=$b is evaluated first, because of the parentheses.
Now, both $a and $b have the
same value, 10. Finally, $c is
assigned the result of the expression $a=$b, which is the value
assigned to the lefthand operand (in this case,
$a). When the full expression is done evaluating,
all three variables contain the same value, 10.

2.4.12.2. Assignment with operation

In addition to the basic assignment
operator, there are several assignment operators that are convenient
shorthand. These operators consist of a binary operator followed
directly by an equals sign, and their effect is the same as
performing the operation with the operands, then assigning the
resulting value to the lefthand operand. These assignment operators
are:

Plus-equals (+=)

Adds the righthand operand to the value of the lefthand operand, then
assigns the result to the lefthand operand. $a+=5 is the same as
$a=$a+5.

Minus-equals (-=)

Subtracts the righthand operand from the value of the lefthand
operand, then assigns the result to the lefthand operand.

Divide-equals (/=)

Divides the value of the lefthand operand by the righthand operand,
then assigns the result to the lefthand operand.

Multiply-equals (*=)

Multiplies the righthand operand with the value of the lefthand
operand, then assigns the result to the lefthand operand.

Modulus-equals (%=)

Performs the modulus operation on the value of the lefthand operand
and the righthand operand, then assigns the result to the lefthand
operand.

Bitwise-XOR-equals (^=)

Performs a bitwise XOR on the lefthand and righthand operands, then
assigns the result to the lefthand operand.

Bitwise-AND-equals (&=)

Performs a bitwise AND on the value of the lefthand operand and the
righthand operand, then assigns the result to the lefthand operand.

Bitwise-OR-equals (|=)

Performs a bitwise OR on the value of the lefthand operand and the
righthand operand, then assigns the result to the lefthand operand.

Concatenate-equals (.=)

Concatenates the righthand operand to the value of the lefthand
operand, then assigns the result to the lefthand operand.

2.4.13. Miscellaneous Operators

The
remaining PHP operators are for error suppression, executing an
external command, and selecting values:

Error suppression (@)

Some operators or functions can generate error messages. The error
suppression operator, discussed in full in Chapter 13, is used to prevent these messages from being
created.

Execution (`...`)

The backtick operator executes the string contained between the
backticks as a shell command and returns the output. For example:

$listing = `ls -ls /tmp`;
echo $listing;

Conditional (?:)

The conditional operator is, depending on the code you look at,
either the most overused or most underused operator. It is the only
ternary (three-operand) operator and is therefore sometimes just
called the ternary operator.

The conditional operator evaluates the expression before the
?. If the expression is true,
the operator returns the value of the expression between the
? and :; otherwise, the
operator returns the value of the expression after the
:. For instance:

<a href="<?= $url ?>"><?= $linktext ? $linktext : $url ?></a>

If text for the link $url is present in the
variable $linktext, it is used as the text for the
link; otherwise, the URL itself is displayed.