Categories
Uncategorized

In PHP, There’s Equality, and Then There’s EQUALITY

Ka=Ping Yee’s Equality Test

Here’s a quickie PHP script based on the one that appears in Ka-Ping Yee’s LiveJournal entry titled Why PHP Should Never Be Taught:

<?php
$a = 0;
$b = "eggs";
$c = "spam";
$e = "eggs";

echo "<h1>The \"==\" Exercise</h1>";
echo "<ul>";
echo "<li>\$a is $a</li>";
echo "<li>\$b is $b</li>";
echo "<li>\$c is $c</li>";
echo "<li>\$d is undefined</li>";
echo "<li>\$e is $e</li>";
echo "</ul>";

echo ($a == $b) ? "\$a == \$b<br />" : "\$a != \$b<br />";
echo ($b == $c) ? "\$b == \$c<br />" : "\$b != \$c<br />";
echo ($a == $c) ? "\$a == \$c<br />" : "\$a != \$c<br />";
echo ($a == $d) ? "\$a == \$d<br />" : "\$a != \$d<br />";
echo ($b == $d) ? "\$b == \$d<br />" : "\$b != \$d<br />";
echo ($c == $d) ? "\$c == \$d<br />" : "\$c != \$d<br />";
echo ($b == $e) ? "\$b == \$e<br />" : "\$b != \$e<br />";
?>

If you’re not familiar with PHP’s quirks, you’ll find the output surprising:

The “==” Exercise

  • $a is 0
  • $b is eggs
  • $c is spam
  • $d is undefined
  • $e is eggs

$a == $b
$b != $c
$a == $c
$a == $d
$b != $d
$c != $d
$b == $e

What Happened?

In PHP, as with many other programming languages, the == operator is the equality operator, which returns true if the operands on either side are equal in value. It works as expected when used on operands of the same type, as evidenced by the program above, which states that $b is equal in value to $e, both of which are set to the string eggs.

We get into strange territory when the == operator is used to compare operands of different types. The program above evaluates the boolean $a == $b as true even though $a is set to the integer value 0 and $b is set to the value eggs. How can eggs be equivalent to 0? They’re so tasty and versatile! Damned anti-ovites!

In PHP, the == operator is what I like to call the “Slack Equality Operator”. When used to compare a string and a number, it attempts to convert the string to a numeric type and then performs the comparison. The following example code, taken from the PHP documentation, shows how PHP’s string-to-number coercion works:

<?php
$foo = 1 + "10.5";                // $foo is float (11.5)
$foo = 1 + "-1.3e3";              // $foo is float (-1299)
$foo = 1 + "bob-1.3e3";           // $foo is integer (1)
$foo = 1 + "bob3";                // $foo is integer (1)
$foo = 1 + "10 Small Pigs";       // $foo is integer (11)
$foo = 4 + "10.2 Little Piggies"; // $foo is float (14.2)
$foo = "10.0 pigs " + 1;          // $foo is float (11)
$foo = "10.0 pigs " + 1.0;        // $foo is float (11)
?>

Hence the eggs/zero equivalence: the string eggs is coerced to 0.

Enter the === Operator

I like to call the === the “Strict Equality Operator”. It returns true if and only if:

  • Both operands are the same type
  • Both operands have the same value

Here’s the code I showed at the start of the article, but with all instances of == replaced with ===:

<?php
$a = 0;
$b = "eggs";
$c = "spam";
$e = "eggs";

echo "<h1>The \"===\" Exercise</h1>";
echo "<ul>";
echo "<li>\$a is $a</li>";
echo "<li>\$b is $b</li>";
echo "<li>\$c is $c</li>";
echo "<li>\$d is undefined</li>";
echo "<li>\$e is $e</li>";
echo "</ul>";

echo ($a === $b) ? "\$a === \$b<br />" : "\$a != \$b<br />";
echo ($b === $c) ? "\$b === \$c<br />" : "\$b != \$c<br />";
echo ($a === $c) ? "\$a === \$c<br />" : "\$a != \$c<br />";
echo ($a === $d) ? "\$a === \$d<br />" : "\$a != \$d<br />";
echo ($b === $d) ? "\$b === \$d<br />" : "\$b != \$d<br />";
echo ($c === $d) ? "\$c === \$d<br />" : "\$c != \$d<br />";
echo ($b === $e) ? "\$b === \$e<br />" : "\$b != \$e<br />";
?>

Here’s the output, which behaves as expected:

The “===” Exercise

  • $a is 0
  • $b is eggs
  • $c is spam
  • $d is undefined
  • $e is eggs

$a != $b
$b != $c
$a != $c
$a != $d
$b != $d
$c != $d
$b === $e

Once More, in Ruby

Just for kicks, I thought I’d translate the original code into Ruby just to see what would happen. Here’s the code:

a = 0
b = "eggs"
c = "spam"
e = "eggs"

puts "a is 0"
puts "b is 'eggs'"
puts "c is 'spam'"
puts "e is 'eggs'"

puts a == b ? "a == b" : "a != b"
puts b == c ? "b == c" : "b != c"
puts a == c ? "a == c" : "a != c"
puts a == d ? "a == d" : "a != d"
puts b == d ? "b == d" : "b != d"
puts c == d ? "c == d" : "c != d"
puts b == e ? "b == e" : "b != e"

…and here’s the output:

a is 0
b is 'eggs'
c is 'spam'
e is 'eggs'
a != b
b != c
a != c
double-equals.rb:14: undefined local variable or method `d' for main:Object (NameError)

Links

One reply on “In PHP, There’s Equality, and Then There’s EQUALITY”

Comments are closed.