Programming PHPProgramming PHPSearch this book

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:

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:

"9 Lives" - 1;              // 8 (int)
"3.14 Pies" * 2;            // 6.28 (float)
"9 Lives." - 1;             // 8 (float)
"1E3 Points of Light" + 1;  // 1001 (float)

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:

$n = 5;
$s = 'There were ' . $n . ' ducks.';
// $s is 'There were 5 ducks'

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:

class Person {
  var $name = "Fred";
  var $age  = 35;
}
$o = new Person;
$a = (array) $o;
print_r($a);
Array
(
    [name] => Fred
    [age] => 35
)

You can cast an array to an object to build an object whose properties correspond to the array's keys and values. For example:

$a = array('name' => 'Fred', 'age' => 35, 'wife' => 'Wilma');
$o = (object) $a;
echo $o->name;
Fred

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.



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.