Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Underlying philosophy behind php type comparisons

So there's this page on the php site which shows the result of comparing different values:

http://php.net/manual/en/types.comparisons.php

This is a helpful reference, but I would rather not have to visit this page every time I want to make sure that I'm doing type comparison right. So my question is

Is there some kind of underlying philosophy/reasoning behind the logic of type comparisons on PHP?

For example, I can see that for loose comparisons:

  • 1, -1, "1" and "-1" can be treated as TRUE and 0 and "0" can be treated as FALSE;
  • Comparing the string value of a number against the number itself with yield TRUE;

but it becomes a bit hairy from then on trying to establish a pattern.

like image 652
Tola Odejayi Avatar asked Apr 16 '13 22:04

Tola Odejayi


People also ask

How PHP compares data of different types?

In PHP, variables of different data types can be compared using the loose comparison operator which is two equal signs (==). If two operands of different types are compared using loose comparison then there is an attempt to convert one or both of the operands and then compare them.

How does PHP compare strings with comparison operators?

PHP will compare alpha strings using the greater than and less than comparison operators based upon alphabetical order. In the first example, ai comes before i in alphabetical order so the test of > (greater than) is false - earlier in the order is considered 'less than' rather than 'greater than'.

What is the difference between == and === comparison operators in PHP?

== Operator: This operator is used to check the given values are equal or not. If yes, it returns true, otherwise it returns false. === Operator: This operator is used to check the given values and its data type are equal or not. If yes, then it returns true, otherwise it returns false.


2 Answers

For casting directly to a boolean this is how it works.

  • All string with a length > 0 are true
  • All non 0 numbers are true
  • All non-empty arrays are true
  • All objects are true

Then these rules for comparing variables of the same type:

  1. Objects are equivalent if their properties are equal
  2. Arrays are equivalent if their keys and elements are equal
  3. Strings are equivalent if they would produce the same output
  4. Numbers are equivalent if they are mathematically equivalent
  5. Booleans are equivalent if they have the same value.

For variable of different types the type that is higher on the above list is cast to the one that is lower then the comparison is made.

=== and !== operators don't cast prior to comparing but you should note objects are only === if they are the same instance.

The really odd one is arrays, they are === if they have the same keys and values defined in the same order.

$a = array("a"=>1, "b"=>2);
$b = array("b"=>2, "a"=>1);

$a == $b; // true
$a === $b; // false

and empty() is equivalent to !(bool)$var

EXCEPTIONS

  • Casting an array to a string will trigger a notice and unhelpfully cast as the text Array
  • Casting an object without a __toString method to a string will get you a fatal error.
  • Objects will not implicitly cast to an array, so any time you compare an object to an array it will yield a false (UPDATE confirmed that this is true even if object implemtents the ArrayAccess interface)
like image 107
Orangepill Avatar answered Nov 06 '22 20:11

Orangepill


For strict === comparision, the logic is easy: each value entity is equal only to itself, so TRUE === TRUE, "1" === "1", but "1" !== 1 etc.

When it comes to == comparision, unfortunately there is no rule of thumb nor a clear logic. This is probably because the various forms of the operator were implemented by different programmers, without a central design decision. The best I can do is providing you with this graph to print and stick over the monitor:

PHP equality graph

The key of the grap is: A == B will be TRUE if and only if A and B are of two types directly connected by a line in the graph above. For instance, array() == NULL is TRUE because array() and NULL are directly connected, while array() == 0 is FALSE because there is no line connecting the two.

Lines marked in red are the tricky (non obvious) equalities.

I've omitted that each entity will be equal to itself (e.g. "1" == "1" etc.) but that should be easy to remember.

As a final note, I'd like to explain why "php" == 0 is TRUE (non empty, non number string is equal to 0): because PHP casts "php" to number before comparision and, since it's not a number, it defaults to 0 and makes the test TRUE.

Fun fact: there is no partition in this relation! If ever a transitive closure was allowed, you could easily say that True is False and False is True, destroying millennia of philosphy in four easy PHP statements :D

like image 27
Stefano Sanfilippo Avatar answered Nov 06 '22 20:11

Stefano Sanfilippo