ConFoo: Call for paper is now Open

PHP type comparison tables

The following tables demonstrate behaviors of PHP types and comparison operators, for both loose and strict comparisons. This supplemental is also related to the manual section on type juggling. Inspiration was provided by various user comments and by the work over at » BlueShoes.

Before utilizing these tables, it's important to understand types and their meanings. For example, "42" is a string while 42 is an integer. FALSE is a boolean while "false" is a string.

Note:

HTML Forms do not pass integers, floats, or booleans; they pass strings. To find out if a string is numeric, you may use is_numeric().

Note:

Simply doing if ($x) while $x is undefined will generate an error of level E_NOTICE. Instead, consider using empty() or isset() and/or initialize your variables.

Note:

Some numeric operations can result in a value represented by the constant NAN. Any loose or strict comparisons of this value against any other value, including itself, will have a result of FALSE. (i.e. NAN != NAN and NAN !== NAN) Examples of operations that produce NAN include sqrt(-1), asin(2), and asinh(0).

Comparisons of $x with PHP functions
Expression gettype() empty() is_null() isset() boolean : if($x)
$x = ""; string TRUE FALSE TRUE FALSE
$x = null NULL TRUE TRUE FALSE FALSE
var $x; NULL TRUE TRUE FALSE FALSE
$x is undefined NULL TRUE TRUE FALSE FALSE
$x = array(); array TRUE FALSE TRUE FALSE
$x = false; boolean TRUE FALSE TRUE FALSE
$x = true; boolean FALSE FALSE TRUE TRUE
$x = 1; integer FALSE FALSE TRUE TRUE
$x = 42; integer FALSE FALSE TRUE TRUE
$x = 0; integer TRUE FALSE TRUE FALSE
$x = -1; integer FALSE FALSE TRUE TRUE
$x = "1"; string FALSE FALSE TRUE TRUE
$x = "0"; string TRUE FALSE TRUE FALSE
$x = "-1"; string FALSE FALSE TRUE TRUE
$x = "php"; string FALSE FALSE TRUE TRUE
$x = "true"; string FALSE FALSE TRUE TRUE
$x = "false"; string FALSE FALSE TRUE TRUE

Loose comparisons with ==
TRUE FALSE 1 0 -1 "1" "0" "-1" NULL array() "php" ""
TRUE TRUE FALSE TRUE FALSE TRUE TRUE FALSE TRUE FALSE FALSE TRUE FALSE
FALSE FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE TRUE TRUE FALSE TRUE
1 TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
0 FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE TRUE FALSE TRUE TRUE
-1 TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
"1" TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
"0" FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
"-1" TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
NULL FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE TRUE TRUE FALSE TRUE
array() FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE
"php" TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
"" FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE

Strict comparisons with ===
TRUE FALSE 1 0 -1 "1" "0" "-1" NULL array() "php" ""
TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
1 FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
0 FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
-1 FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
"1" FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
"0" FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
"-1" FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
NULL FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE
array() FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE
"php" FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
"" FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE

add a note add a note

User Contributed Notes 14 notes

up
26
php at richardneill dot org
2 years ago
Be wary of string-comparison where both strings might be interpreted as numbers.  Eg:

$x="123456789012345678901234567890"; $y="123456789012345678900000000000";
echo  ($x==$y)?"equal":"not_equal";   #Prints equal !!

Both strings are getting converted to floats, then losing precision, then becoming equal :-(

Using "===" or making either of the strings non-numeric will prevent this.
[This is on a 32-bit machine, on a 64-bit, you will have to make the strings longer to see the effect]
up
10
frank
7 years ago
A comparison table for <=,<,=>,> would be nice...
Following are TRUE (tested PHP4&5):
NULL <= -1
NULL <= 0
NULL <= 1
!(NULL >= -1)
NULL >= 0
!(NULL >= 1)
That was a surprise for me (and it is not like SQL, I would like to have the option to have SQL semantics with NULL...).
up
8
edgar at goodforall dot eu
4 years ago
Some function to write out your own comparisson table in tsv format. Can be easily modified to add more testcases and/or binary functions. It will test all comparables against each other with all functions.

<?php
$funcs
= array(
       
/* Testing equality */
       
'eq' => '==',
       
'ne' => '!=',
       
'gt' => '>',
       
'lt' => '<',
       
'ne2' => '<>',
       
'lte' => '<=',
       
'gte' => '>=',
       
/* Testing identity */
       
'id' => '===',
       
'nid' => '!=='
);
class
Test {
        protected
$a;
        public
$b;
        public function
__construct($a,$b){
               
$this->a = $a;
               
$this->b = $b;
        }
        public function
getab(){
                return
$this->a.",". $this->b;
        }

}
$tst1 = new Test(1,2);
$tst2 = new Test(1,2);
$tst3 = new Test(2,2);
$tst4 = new Test(1,1);

$arr1 = array(1,2,3);
$arr2 = array(2,3,4);
$arr3 = array('a','b','c','d');
$arr4 = array('a','b','c');
$arr5 = array();

$comp1 = array(
       
'ints' => array(-1,0,1,2),
       
'floats' => array(-1.1,0.0,1.1,2.0),
       
'string' => array('str', 'str1', '', '1'),
       
'bools' => array(true, false),
       
'null' => array(null),
       
'objects' => array($tst1,$tst2,$tst3,$tst4),
       
'arrays' => array($arr1, $arr2, $arr3, $arr4, $arr5)
);
$fbody = array();

foreach(
$funcs as $name => $op){
       
$fbody[$name] = create_function('$a,$b', 'return $a ' . $op . ' $b;');
}

$table = array(array('function', 'comp1', 'comp2', 'f comp1 comp2', 'type'));
/* Do comparisons */
$comp2  = array();
foreach(
$comp1 as $type => $val){
       
$comp2[$type] = $val;
}

foreach(
$comp1 as $key1 => $val1){
        foreach(
$comp2 as $key2 => $val2){
               
addTableEntry($key1, $key2, $val1, $val2);
        }
}
$out = '';
foreach(
$table as $row){
       
$out .= sprintf("%-20s\t%-20s\t%-20s\t%-20s\t%-20s\n", $row[0], $row[1], $row[2], $row[3], $row[4]);
}

print
$out;
exit;

function
addTableEntry($n1, $n2, $comp1, $comp2){
        global
$table, $fbody;
        foreach(
$fbody as $fname => $func){
                        foreach(
$comp1 as $val1){
  foreach(
$comp2 as $val2){
                                       
$val = $func($val1,$val2);
                                               
$table[] = array($fname, gettype($val1) . ' => ' . sprintval($val1), gettype($val2) .' => ' . sprintval($val2), gettype($val) . ' => ' . sprintval($val), gettype($val1) . "-" . gettype($val2) . '-' . $fname);
                                        }
                        }
        }
}

function
sprintval($val){
        if(
is_object($val)){
                return
'object-' . $val->getab();
        }
        if(
is_array($val)){
                return
implode(',', $val);
        }
        if(
is_bool($val)){
                if(
$val){
                        return
'true';
                }
                return
'false';
        }
        return
strval($val);
}

?>
up
9
Jan
8 years ago
Note that php comparison is not transitive:

"php" == 0 => true
0 == null => true
null == "php" => false
up
5
aidan at php dot net
9 years ago
The way PHP handles comparisons when multiple types are concerned is quite confusing.

For example:
"php" == 0

This is true, because the string is casted interally to an integer. Any string (that does not start with a number), when casted to an integer, will be 0.
up
4
php at benizi dot com
4 years ago
It's interesting to note that 'empty()' and 'boolean : if($x)'
are paired as logical opposites, as are 'is_null()' and 'isset()'.
up
6
jerryschwartz at comfortable dot com
9 years ago
In some languages, a boolean is promoted to an integer (with a value of 1 or -1, typically) if used in an expression with an integer. I found that PHP has it both ways:

If you add a boolean with a value of true to an integer with a value of 3, the result will be 4 (because the boolean is cast as an integer).

On the other hand, if you test a boolean with a value of true for equality with an integer with a value of three, the result will be true (because the integer is cast as a boolean).

Surprisingly, at first glance, if you use either < or > as the comparison operator the result is always false (again, because the integer as cast as a boolean, and true is neither greater nor less than true).
up
4
crazy888s at hotmail dot com
1 year ago
PHP's loose comparisons can be a huge convenience when used properly! It's extremely helpful to just remember the following are always FALSE:

null, false, "", 0, "0", array()

If your application never depends on a particular "empty/false/null/0/not set" value type, you won't have to worry about 99% of the other weird cases listed here. You won't need empty() or isset(). And ALL variable types will always work as expected for statements like:

if(boolean && !string){...}
if(array){...}
if(!null || int){...}

Consider the same when working with your database values.
up
2
tom
9 years ago
<?php
if (strlen($_POST['var']) > 0) {
   
// form value is ok
}
?>

When working with HTML forms this a good way to:

(A) let "0" post values through like select or radio values that correspond to array keys or checkbox booleans that would return FALSE with empty(), and;
(B) screen out $x = "" values, that would return TRUE with isset()!

Because HTML forms post values as strings, this is a good way to test variables!

[[Editor Note: This will create a PHP Error of level E_NOTICE if the checked variable (in this case $_POST['var']) is undefined. It may be used after (in conjuection with) isset() to prevent this.]]
up
2
info at shaelf dot ru
6 years ago
Compare object
<?php
$o
= new stdClass();
$o->we = 12;

$o2 = new stdClass();
$o2->we = 12;

$o3 = clone $o2;
var_dump($o == $o2); //true
var_dump($o === $o2); //false
var_dump($o3 === $o2); //true
?>
up
0
blue dot hirano at gmail dot com
10 days ago
The truth tables really ought to be colorized; they're very hard to read as they are right now (just big arrays of TRUE and FALSE).

Also, something to consider: clustering the values which compare similarly (like is done on qntm.org/equality) would make the table easier to read as well. (This can be done simply by hand by rearranging the order of headings to bring related values closer together).
up
-2
Anonymous
9 months ago
I'm running PHP 5.5.3.

This is a correction to one of the previous posts.

<?php
$o
= new stdClass();
$o->we = 12;

$o2 = new stdClass();
$o2->we = 12;

$o3 = clone $o2;
var_dump($o == $o2); //true
var_dump($o === $o2); //false
var_dump($o3 === $o2); //false
?>

Output is:

true, false, false
up
-5
Jouriy LYSENKO
3 years ago
If $var not declared.

In php 5.2 :
<?php if($var) ?> - work

in php 5.3 :
<?php if($var) ?> - dont work and generate error E_NOTICE
up
-5
lorenzo dot campagna at ymail dot com
7 months ago
Someone can explain why this comparison result TRUE  when it should be FALSE?

<?php

$a
= "3abcdef";
$b = 3;

if(
$a == $b) {print("Match!");}    //Because of this comparison TRUE script will output:

?>
To Top