Таблица сравнения типов в PHP
Следующие таблицы демонстрируют работу PHP с типами переменных и операторами сравнения, как в случае свободного, так и в случае строгого сравнения. Также эта информация относится к разделу документации по приведению типов. Вдохновением на создание этого раздела мы обязаны различным комментариям пользователей и работе над » BlueShoes.
До осмотра таблиц, важно знать и понимать типы переменных и их значения.
К примеру, "42" - string,
в то время как 42 - integer. FALSE
-
boolean, а "false" -
string.
Замечание:
HTML-формы не передают целые, дробные числа или булевые переменные: они всегда передают строки. Для проверки является ли строка числом, используйте функцию is_numeric().
Замечание:
Использование if ($x), если $x не определена, сгенерирует ошибку уровня
E_NOTICE
. Вместо этого используйте функцию empty() или isset() и/или инициализируйте переменную.
Замечание:
Некоторые арифметические операции могут вернуть значение, представленное константой
NAN
(Not A Number, не-число). Любое строгое или нестрогое сравнение этого значения с каким-либо другим, включая его самого, вернетFALSE
(т.е. NAN != NAN и NAN !== NAN). Примерами операций, возвращающихNAN
, являются sqrt(-1), asin(2) и asinh(0).
Выражение | 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 не определена | 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 |
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 |
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 |
- История PHP и смежных проектов
- Migrating from PHP 7.0.x to PHP 7.1.x
- Migrating from PHP 5.6.x to PHP 7.0.x
- Migrating from PHP 5.5.x to PHP 5.6.x
- Migrating from PHP 5.4.x to PHP 5.5.x
- Переход с PHP 5.3.x на PHP 5.4.x
- Переход c PHP 5.2.x на PHP 5.3.x
- Переход с PHP 5.1.x на PHP 5.2.x
- Переход с PHP 5.0.x на PHP 5.1.x
- Переход с PHP 4 на PHP 5.0.x
- Classes and Objects (PHP 4)
- Отладка в PHP
- Опции конфигурации
- Директивы php.ini
- Список/классификация расширений
- Список псевдонимов функций
- Список зарезервированных слов
- Список типов ресурсов
- Список доступных фильтров
- Список поддерживаемых транспортных протоколов
- Таблица сравнения типов в PHP
- Список меток (tokens) парсера
- Руководство по именованию
- Об этом руководстве
- Creative Commons Attribution 3.0
- Алфавитный список
- Список изменений
Коментарии
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.
<?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.]]
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).
Note that php comparison is not transitive:
"php" == 0 => true
0 == null => true
null == "php" => false
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...).
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
?>
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);
}
?>
It's interesting to note that 'empty()' and 'boolean : if($x)'
are paired as logical opposites, as are 'is_null()' and 'isset()'.
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
[Editor's note: As of PHP 5.4.4 this is no longer true. Integral strings that overflow into floating point numbers will no longer be considered equal.]
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]
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.
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
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).
The loose comparison chart is missing a few things.
array(1)==true returns true.
also:
(int)array(1) === 1 returns true
This is symmetric:
array(1) === (array)1 returns true
but the loose comparison
array(1)==1 still returns false.
please note that
$x = 0.0 ;
print empty($x); // returns 1 (true)
$x = "0.0";
print empty($x); // returns blank (false);
If you want to view the truth tables colorized, just:
1. Save a local copy of this page as an .html file,
2. View the page source with any text editor.
3. Replace the opening <head> tag so it will include this:
<head>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
4. Replace the closing </body> tag with this:
<script>
$( "td:contains('FALSE')" ).css("color", "red");
$( "td:contains('TRUE')" ).css("color", "green");
</script>
</body>
5. Save the file, and view it on your browser. Enjoy.
If you want to calculate how much more/less items by the criterion
Example:
in loop:
$counter += intval($item->isValid()) <=> 0.5;
if $counter >= 0 - valid items are more then invalid on $counter
if $counter < 0 - valid items are less then invalid on $counter
Want to strictly compare integers that may or may not be converted to floats (via PHPExcel import/export, etc.)? You are out of luck:
var_dump( (int)1 === (int)1 ); // bool(true)
var_dump( (float)1 === (float)1 ); // bool(true)
var_dump( (float)1 === (int)1 ); // bool(false)
var_dump( (int)1 === (float)1 ); // bool(false)
This slightly complicated function might help you:
function equal_numbers( $a, $b ){
if( $a === $b ) return true;
if( is_int( $a ) && is_float( $b )) return (float)$a === $b && $a === (int)$b;
if( is_float( $a ) && is_int( $b )) return (int)$a === $b && $a === (float)$b;
return false;
}
Here are some tests:
test(100, 100.0 ); // int(100) float(100) bool(true)
test( 0, -0 ); // int(0) int(0) bool(true)
test( -0, -0.0 ); // int(0) float(-0) bool(true)
test( 0, 1/0 ); // int(0) float(INF) bool(false)
test( 0, acos(2));// int(0) float(NAN) bool(false)
test( PHP_INT_MAX * 10, 0 ); //float(92233720368547758080) int(0) bool(false)
test((float)PHP_INT_MAX, PHP_INT_MAX );//float(9223372036854775808) int(9223372036854775807) bool(false)
test((float)PHP_INT_MAX / 2, PHP_INT_MAX / 2 );//float(4611686018427387904) float(4611686018427387904) bool(true)
function test( $a, $b ){
var_dump( $a, $b, equal_numbers( $a, $b ));
}
Here's how PHP handles loose and strict comparisons of default parameters in functions:
Very unintuitive:
<?php
function f($x='surprise')
{
if ($x == 'surprise')
return $x; // returns 0 !!
}
echo f(0);
?>
Here some further tests:
<?php
function f($x='surprise')
{
if ($x == 'surprise')
return 'A:'.$x;
if ($x === 'surprise')
return 'B:'.$x;
return 'C:'.$x;
}
echo "\n".f(0); // A:0 !!
echo "\n".f(0.0); // A:0 !!
echo "\n".f(NULL); // C: !!
echo "\n".f(FALSE); // C:
echo "\n".f(); // A:surprise
echo "\n".f(''); // C:
echo "\n".f((integer)0); // A:0
echo "\n".f((string)0); // C:0
echo "\n".f('0'); // C:0
echo "\n".f(0.1); // C:0.1
echo "\n".f(array()); // C:Array
echo "\n".f('surprise'); // A:surprise
?>
There is also 0.0 which is not identical to 0.
$x = 0.0;
gettype($x); // double
empty($x); // true
is_null($x); //false
isset($x); // true
is_numeric($x); // true
$x ? true : false; // false
$x == 0; // true
$x == "0"; // true
$x == "0.0"; // true
$x == false; // true
$x == null; // true
$x === 0; // false
$x === false; // false
$x === null; // false
$x === "0"; // false
$x === "0.0"; // false
regarding the editors note in php at richardneill dot org note:
[Editor's note: As of PHP 5.4.4 this is no longer true. Integral strings that overflow into floating point numbers will no longer be considered equal.]
While this is true, there is still the following behaviour:
<?php
$x = "1";
$y = "+1";
var_dump($x == $x);
?>
outputs "bool(true)".
So still be wary of string-comparison where both strings might be interpreted as numbers.
<?php
echo md5('240610708') == md5('QNKCDZO') ? "equal" : "not equal"; // prints equal!!!
I noticed that some "magic" also happens when comparing strings with leading zeros with only two equal signs:
<?php
var_dump('1' == '01');
var_dump('01' == '000001');
?>
Output:
bool(true)
bool(true)
If the string contains only numbers all leading zeroes seem to be ignored.