Comparison Operators

Comparison operators, as their name implies, allow you to compare
two values. You may also be interested in viewing
the type comparison tables,
as they show examples of various type related comparisons.

Comparison Operators

Example

Name

Result

$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.

$a != $b

Not equal

TRUE if $a is not equal to $b after type juggling.

$a <> $b

Not equal

TRUE if $a is not equal to $b after type juggling.

$a !== $b

Not identical

TRUE if $a is not equal to $b, or they are not of the same
type.

$a < $b

Less than

TRUE if $a is strictly less than $b.

$a > $b

Greater than

TRUE if $a is strictly greater than $b.

$a <= $b

Less than or equal to

TRUE if $a is less than or equal to $b.

$a >= $b

Greater than or equal to

TRUE if $a is greater than or equal to $b.

If you compare a number with a string or the comparison involves numerical
strings, then each string is
converted to a number
and the comparison performed numerically. These rules also apply to the
switch statement. The
type conversion does not take place when the comparison is === or !== as
this involves comparing the type as well as the value.

The expression (expr1) ? (expr2) : (expr3)
evaluates to expr2 if
expr1 evaluates to TRUE, and
expr3 if
expr1 evaluates to FALSE.

Since PHP 5.3, it is possible to leave out the middle part of the ternary
operator. Expression expr1 ?: expr3 returns
expr1 if expr1
evaluates to TRUE, and expr3 otherwise.

Note:
Please note that the ternary operator is an expression, and that it
doesn't evaluate to a variable, but to the result of an expression. This
is important to know if you want to return a variable by reference.
The statement return $var == 42 ? $a : $b; in a
return-by-reference function will therefore not work and a warning is
issued in later PHP versions.

Note:

It is recommended that you avoid "stacking" ternary expressions. PHP's
behaviour when using more than one ternary operator within a single
statement is non-obvious:

Example #4 Non-obvious Ternary Behaviour

<?php// on first glance, the following appears to output 'true'echo (true?'true':false?'t':'f');

// however, the actual output of the above is 't'// this is because ternary expressions are evaluated from left to right

// the following is a more obvious version of the same code as aboveecho ((true ? 'true' : false) ? 't' : 'f');

// here, you can see that the first expression is evaluated to 'true', which// in turn evaluates to (bool)true, thus returning the true branch of the// second ternary expression.?>

User Contributed Notes 47 notes

The following contrasts the trinary operator associativity in PHP and Java. The first test would work as expected in Java (evaluates left-to-right, associates right-to-left, like if stmnt), the second in PHP (evaluates and associates left-to-right)

I discover after 10 years of PHP development something awfull : even if you make a string comparison (both are strings), strings are tested like integers and leading "space" character (even \n, \r, \t) is ignored ....

I spent hours because of leading \n in a string ... it hurts my developper sensibility to see two strings beeing compared like integers and not like strings ... I use strcmp now for string comparison ... so stupid ...

note: the behavior below is documented in the appendix K about type comparisons, but since it is somewhat buried i thought i should raise it here for people since it threw me for a loop until i figured it out completely.

just to clarify a tricky point about the == comparison operator when dealing with strings and numbers:

('some string' == 0) returns TRUE

however, ('123' == 0) returns FALSE

also note that ((int) 'some string') returns 0

and ((int) '123') returns 123

the behavior makes senes but you must be careful when comparing strings to numbers, e.g. when you're comparing a request variable which you expect to be numeric. its easy to fall into the trap of:

if ($_GET['myvar']==0) dosomething();

as this will dosomething() even when $_GET['myvar'] is 'some string' and clearly not the value 0

i was getting lazy with my types since php vars are so flexible, so be warned to pay attention to the details...

I think everybody should read carefully what "jeronimo at DELETE_THIS dot transartmedia dot com" wrote. It's a great pitfall even for seasoned programmers and should be looked upon with a great attention.For example, comparing passwords with == may result in a very large security hole.

I would add some more to it:

The workaround is to use strcmp() or ===.

Note on ===:

While the php documentation says that, basically,($a===$b) is the same as ($a==$b && gettype($a) == gettype($b)),this is not true.

The difference between == and === is that === never does any type conversion. So, while, according to documentation, ("+0.1" === ".1") should return true (because both are strings and == returns true), === actually returns false (which is good).

You can't just compare two arrays with the === operator
like you would think to find out if they are equal or not. This is more complicated when you have multi-dimensional arrays. Here is a recursive comparison function.

<?php
/**
* Compares two arrays to see if they contain the same values. Returns TRUE or FALSE.
* usefull for determining if a record or block of data was modified (perhaps by user input)
* prior to setting a "date_last_updated" or skipping updating the db in the case of no change.
*
* @param array $a1
* @param array $a2
* @return boolean
*/
function array_compare_recursive($a1, $a2)
{
if (!(is_array($a1) and (is_array($a2)))) { return FALSE;}

if (!count($a1) == count($a2))
{
return FALSE; // arrays don't have same number of entries
}

Note that the "ternary operator" is better described as the "conditional operator". The former name merely notes that it has three arguments without saying anything about what it does. Needless to say, if PHP picked up any more ternary operators, this will be a problem.

"Conditional Operator" is actually descriptive of the semantics, and is the name historically given to it in, e.g., C.

# May work with warnings that $tally[$index] is not initialized
# Notice: Undefined offset: 1 in D:\htdocs\colors\ColorCompare\i.php on line #__
# It is an old fashioned way.
# $tally[$index] = $tally[$index] + 1;

We have seen that PHP does a lot of type-juggling on its own -- which can wreak havoc in unexpected ways -- but it is still up to us to produce code that is clear, maintainable AND follows the rules we want to follow.

When creating a PHP Object, it is sometimes unclear what makes two of them the same. But the good part is that we can say what is equal and what is not equal. For example, let's say we have a Student class that includes an equals() method which defines what is equal for this type of object.

/* * This function requires an instance of type Student and * only evaluates two integers that we set in __construct(). */public function equals(Student $student) { return ($this->getId() == $student->getId()); }

With this class, the protected variables cannot be tampered with by outside code. Also, the __construct() function casts the variables to the PHP primitives WE WANT, while the equals(Student $student) function, requires an argument of type Student -- which eliminates the need for an IDENTITY '===' check AND prevents any other data types from coming in. One other note: notice how the equals() function only evaluates the $student_id, this allows for two students to have the same name -- which is totally possible.

Here's a short example -- we'll do it correctly AND try to screw it up!

See what I mean by writing code that follows OUR RULES? The Student class does the kind of type-juggling we want (and when we want it done) -- NOT when, where, or why PHP does it (not that there's anything wrong with it).

This will output 'true == false'. This stems from the use of the UNIX function strtod() to convert strings to numbers before comparing. Since 'X' or any other string without a number in it converts to 0 when compared to a number, 0 == 0 && 'X' == true && 0 == false

Replying to the comment on Aug 6, 2010, the comparisons return TRUE because they are recognized as numerical strings and are converted to integers. If you try "abc" == " abc", it will return FALSE as expected. To avoid the type conversions, simply use the identity operator (===).

"Array with fewer members is smaller, if key from operand 1 is not found in operand 2 then arrays are uncomparable, otherwise - compare value by value (see following example)."

The example covers this behaviour, but it isn't immediately obvious, so:

If you're doing loose comparisons in PHP, note that they differ from checking each value individually like $value1==$value2 by adding what amounts to an empty($value1)==empty($value2) check into the mix. I found this out by investigating some (to me) bizarre behaviour.[Note that the example contains no ==, just > and <. It's its absence that perceivedly 'causes empty() to fire'.]

I was also pleasantly surprised to see PHP recurse. Also clear if you keep in mind that the example implies another function call to itself with > and < if both operands are arrays, but IMO definitely worth stating.

It might also be worth noting that the order of array keys doesn't matter, even if a foreach() would see a 'different' array. Again, covered by the example, but might be worth stressing.

Here is some ternary trick I like to use for selecting a default value in a set of radio buttons. This example assumes that a prior value was known and that we are offering a user the chance to edit that prior value. If no prior value was actually known, no default value will be set.

When a "=" directly follows a "<?" (no space allowed in between -- the trick does not work with "<?php"), the right side of the operand (here, the result of the ternary operation) is printed out as text into the surrounding HTML code. If using "<?php" form, you will need to do "<?php echo exp1?exp2:exp3 ?>" instead.

That can't be read from inside to out, unlike a math formula, because the logic in comparison is not the same. In math nesting, you need the solution to the deepest nested element first. In logic comparison, you always start outside before you compare inside. (Logically, IF there is no door THEN you need something ELSE to get inside. Oh, there is a window... We are inside, now IF there is a fridge THEN open it or ELSE you starve.)

Most of the time, you may be content with your conditionals evaluating to true if they are evaluating a non-false, non-zero value. You may also like it when they evaluate to false when you use the number 0.

However, there may be times where you want to make a distinction between a non-false value and a boolean true. You may also wish to make a distinction between a boolean false and a zero.

You should be very careful when using == with an result set returned from a query that can be an empty array, multi-dimensional array or a boolean false value (if the query failed to execute). In PHP, an empty array is equivalent to true.

<?php
$myArray = array();

// check if there is any error with the query
if ($myArray == false)
{
echo "Yes";
}
?>

When $i is set, you get this:Hello, my friend: Me, how are you doing? (expected)When $i is NOT set, you get this:Hello, my guest, Guest, please register (expected too)

So.. Please, don't be dumb and ALWAYS use the priority-signs (or.. How do you call them?), ( and ).By using them, you won't get unneeded trouble and always know for sure your code is doing what you want: The right thing.

The cast from null to boolean is documented (on the page describing the boolean type: null->false), and so is the cast from boolean to integer (on the page describing the integer type: false->0), but the cast from null to integer is undefined and the fact that it is currently implemented by casting from null to boolean and then from boolean to integer is explicitly documented (on the page describing the integer type) as something that should not be relied on (so null==0 is true only by accident, but ((int)(bool)null)==0 is true per specification).

Perhaps as well as a "Converting to integer" section on the integer type page there should also be a "Converting from integer" section; similarly for the other types.

Since php 5.2 the operator == for object vs object is not recursion safe, it will cause a fatal error if one of the objects contains a refernce to it self (indirect refferences also counts here).If you are just checking if two object pointers points to the same object use === instead and aviod this issue (you might get a minimal speed bost too).