PHPWomen Site Home » Programming » Best Practices » Comparison operators: When equals doesn't equal equals
Comparison operators: When equals doesn't equal equals [message #1140] Fri, 06 April 2007 10:22 Go to next message
KathyReid  is currently offline KathyReid
Messages: 224
Registered: October 2006
Location: Geelong, Victoria, Austra...
Member
This article provides a brief tutorial on a common topic of confusion amongst PHP developers - the seemingly similar operators; equals (==) and identical (===).

During your PHP programming, you will have undoubtedly used the equals operator to perform value comparisons, usually to do conditional processing. For instance;

<?php
$myVar1 
'cat'// a string
$myVar2 'dog'// also a string
$myVar3 'cat'// again a string


// $myVar1 == $myVar2 will evaluate to boolean false
// $myVar1 == $myVar3 will evaluate to boolean true

if ($myVar1 == $myVar2)
{
    echo 
'TRUE';
} else 
{
    echo 
'FALSE';
}

if (
$myVar1 == $myVar3)
{
    echo 
'TRUE';
} else 
{
    echo 
'FALSE';
}


$myVar4 '42'// a string
$myVar5 42// an integer

// $myVar4 == $myVar5 will evaluate to boolean true 
// because == does a value comparison only

if ($myVar4 == $myVar5)
{
    echo 
'TRUE';
} else 
{
    echo 
'FALSE';
}

$myVar6 42.00// a float
$myVar7 42// an integer

// $myVar6 == $myVar7 will evaluate to boolean true
// because == does a value comparison only

if ($myVar6 == $myVar6)
{
    echo 
'TRUE';
} else 
{
    echo 
'FALSE';
}
?>



The identical operator goes one step further, and compares not just the value, but the type of the operands.

Let's use the identical operator on the examples given above and see what happens;

<?php
$myVar1 
'cat'// a string
$myVar2 'dog'// also a string
$myVar3 'cat'// again a string


// $myVar1 === $myVar2 will evaluate to boolean false
// $myVar1 === $myVar3 will evaluate to boolean true  as both type and value are identical

if ($myVar1 === $myVar2)
{
    echo 
'TRUE';
} else 
{
    echo 
'FALSE';
}

if (
$myVar1 === $myVar3)
{
    echo 
'TRUE';
} else 
{
    echo 
'FALSE';
}


$myVar4 '42'// a string
$myVar5 42// an integer

// $myVar4 === $myVar5 will evaluate to boolean false  
// because the types are different - one is a string,  the other an integer

if ($myVar4 === $myVar5)
{
    echo 
'TRUE';
} else 
{
    echo 
'FALSE';
}

$myVar6 42.00// a float
$myVar7 42// an integer

// $myVar6 == $myVar7 will evaluate to boolean false
// because the types are different - one is a float,  the other an integer

if ($myVar6 === $myVar7)
{
    echo 
'TRUE';
} else 
{
    echo 
'FALSE';
}
?>


The identical operator is also useful for comparing arrays;

<?php
$myVar8 
= Array('blue'); // an array with one element
$myVar9 'blue'// a string

// $myVar8 === $myVar9 will evaluate to boolean false
// because one is a string, and the other is an array  of one element (even though the one element is a string)

if ($myVar8 === $myVar9)
{
    echo 
'TRUE';
} else 
{
    echo 
'FALSE';
}


$myVar10 = Array(1,1,3,5,8,13,21,35); // an array of integers
$myVar11 = Array(1.01.03.05.08.013.021.035.0); // an array of floats
$myVar12 = Array('1''1''3''5''8''13''21''35'); // an array of strings

// even though the variables above are all arrays, 
// they are arrays of different types of values (integer,  float, string)
// and are therefore not identical

if ($myVar10 === $myVar11)
{
    echo 
'TRUE';
} else 
{
    echo 
'FALSE';
}

if (
$myVar10 === $myVar12)
{
    echo 
'TRUE';
} else 
{
    echo 
'FALSE';
}

if (
$myVar11 === $myVar12)
{
    echo 
'TRUE';
} else 
{
    echo 
'FALSE';
}
?>


In many cases, the equals operator will be sufficient for the task at hand. However, there are many tasks for which the identical operator is superior;

  • When comparing variables that will be used to update a database (for instance, ensuring that an expected integer value is in fact an integer instead of a string designed to inject malicious SQL)
  • When comparing arrays where elements of the same type (say floats, integers, strings etc) are assumed. Remember, assuming that values passed are those that are expected is a fundamental mistake made by many programmers.
  • Comparing that resources (such as database connections, file handlers etc) are of the expected type.


More information on the equals and identical operator can be found at;

http://au2.php.net/operators.comparison


Re: Comparison operators: When equals doesn't equal equals [message #1170 is a reply to message #1140 ] Sun, 15 April 2007 15:50 Go to previous messageGo to next message
lorna  is currently offline lorna
Messages: 413
Registered: October 2006
Location: Leeds, UK
Feeling Comfortable

Great article Kathy, I often have to stop and think about whether I want "mostly equals" or "definitely-to-the-point-of-obsessive equals" - and this sums it up neatly Smile


Lorna Mitchell (online at http://www.lornajane.net)
Re: Comparison operators: When equals doesn't equal equals [message #1394 is a reply to message #1140 ] Thu, 12 July 2007 16:36 Go to previous messageGo to next message
elfsie  is currently offline elfsie
Messages: 4
Registered: July 2007
Location: Los Angeles, CA
Shiny and New
Hi Kathy & everyone,

I'm new to the site and love it. Thanks for all your hard work and great insights.

About the == versus === issue: I have a session variable that can be unset or set to 0, 1 or "error". Here's an if/else test that sets its value:

//if not yet set, set to 0
if (!isset($_SESSION[$var])){
$_SESSION[$var] = 0;
}

//if set to error (which happens elsewhere), reset to 0
elseif ((isset($_SESSION[$var])) && ($_SESSION[$var]=="error")){
$_SESSION[$var] = 0;
}

else {
$_SESSION[$var] = 1;
}

In the elseif test above, if $_SESSION[$var] is 0, it will pass that test and be set to 0. If I change the == to ===, it then fails the test as it should. But for my future reference and edification, how does 0 sort of equal "error"? Is the string "error" a reserved word, or does it behave like the word false behaves as a boolean? I couldn't find anything in the documentation.

(BTW, how do I keep the indents in my code? They are being stripped out)

Thanks!
Erica C.
Re: Comparison operators: When equals doesn't equal equals [message #1402 is a reply to message #1140 ] Sun, 15 July 2007 00:05 Go to previous messageGo to next message
KathyReid  is currently offline KathyReid
Messages: 224
Registered: October 2006
Location: Geelong, Victoria, Austra...
Member
Hi Elfsie,

Here's a useful approach for investigating this one;

First of all I will make the following assumptions;


  • 'error' is a string literal and has not been defined as a constant. If it is a constant, it should be written as ERROR to fit with industry standards (constants should be referenced as upper case - it makes it easy to know that they are constants Smile )
  • $_SESSION["$var"] is defined as a string ('error' is a string literal)
  • 'error' is not a reserved word according to the reserved words list in the manual http://au3.php.net/manual/en/reserved.php


Next, let's break down the PHP and step it out in plain English;


<?php
//if not yet set, set to 0
if (!isset($_SESSION[$var])){
  
$_SESSION[$var] = 0;
}
?>


If the session variable $var is not set, we will (implictly) set it and (explictly) assign it the value of zero. Zero is an integer in this case as it is not encased in quotes ie '0'.

<?php
//if set to error (which happens elsewhere), reset to  0
elseif ((isset($_SESSION[$var])) && ($_SESSION[$var]=="error")){
  
$_SESSION[$var] = 0;
}
?>


If the session variable $var is set and it is equal in value (not in type) to the string literal "error" then set $var to the integer value of zero.

<?php
else {
  
$_SESSION[$var] = 1;
}
?>


Else set the session variable to the integer value of 1.

So, what does this all mean in terms of comparison operators?

Let's concentrate on this line;

<?php
elseif ((isset($_SESSION[$var])) && ($_SESSION[$var]=="error")){
?>


First of all, "error" is in double quotes. PHP will attempt to evaluate anything in between double quotes and will check here to see if there are any statements for evaluation (see the post about single vs double quotes). Here, it should be written as 'error' because it is being treated as a string literal.

But are "error" and 'error' equal in value and type? Let's find out;

<?php
$dblquotes 
"error";
$sglquotes 'error';

echo 
'Is value equal?';
echo (
$dblquotes == $sglquotes);


echo 
'Are value and type equal?';
echo (
$dblquotes === $sglquotes);
?>


They are equal in value and type - so this is not the issue.

Next, we need to see whether 'error' is a defined constant in PHP (it may not be a reserved word, but it could be a constant).

<?php
echo defined('error');
?>


No - it is not a defined constant.

Next, we can check to see whether 'error' equates to zero;

<?php
echo ('error' == 0);
?>


... which it does ...

This isn't documented anywhere that I could find (ie in the comparison tables for loose and strict comparisons - http://au3.php.net/manual/en/types.comparisons.php)

So - I think the result is that there is an 'undocumented feature' here - unless anyone else knows otherwise?

Cheers,
K.

Oh, and to get the PHP code displaying properly with syntax highlighting, enclose the PHP code in left square bracket, the word php, right square bracket then to end the PHP code, left square bracket, forward slash, the word php then right square bracket - can't find out how to demonstrate it without it formatting the code Smile




[Updated on: Tue, 17 July 2007 08:09]

Re: Comparison operators: When equals doesn't equal equals [message #1423 is a reply to message #1402 ] Mon, 06 August 2007 08:43 Go to previous messageGo to next message
monxton  is currently offline monxton
Messages: 15
Registered: November 2006
Shiny and New
KathyReid wrote on Sun, 15 July 2007 05:05


Next, we can check to see whether 'error' equates to zero;

<?php
echo ('error' == 0);
?>


... which it does ...

This isn't documented anywhere that I could find (i.e. in the comparison tables for loose and strict comparisons - http://au3.php.net/manual/en/types.comparisons.php)

So - I think the result is that there is an 'undocumented feature' here - unless anyone else knows otherwise?


I think it is there in table R2 - the row starting with "php" is supposed to represent any old string, and the table tells us that "php" == 0 will result in TRUE.

This happens because the comparison of a string with a number forces the string to be converted to a number, and since the string does not start with a numeric character, it evaluates to zero. If the string was, for example, "1error", the result would have been FALSE.
Re: Comparison operators: When equals doesn't equal equals [message #1424 is a reply to message #1140 ] Mon, 06 August 2007 09:21 Go to previous messageGo to next message
KathyReid  is currently offline KathyReid
Messages: 224
Registered: October 2006
Location: Geelong, Victoria, Austra...
Member
aaaaaaaah!
Now I see - it's a typecasting issue. Duh! It should have been obvious to me...
Re: Comparison operators: When equals doesn't equal equals [message #1449 is a reply to message #1140 ] Sat, 01 September 2007 00:26 Go to previous messageGo to next message
j.rf  is currently offline j.rf
Messages: 139
Registered: October 2006
Location: The Netherlands
Member
So what is the lesson we learn from this ? (or rather: what is the lesson I have learned from this the hard way some time ago ?)

For well documented and predictable code, ALWAYS use === unless you WANT certain 'unexpected' effects to take place (which some programmers do, but I rather don't want).

A lot of php functions will return false or 0 and these returns will mean different things, so the above (always use === ) is especially important when evaluating the returns of functions.

Just an obvious example which comes to mind:
strpos()

Here's another nasty one for if you don't realise (or temporarily forget) all the intricaties of how it works:
empty()

I've created a far more extensive types.comparison table for my own private use which will demonstrate some of those pittfalls quite easily.
NOTE TO SELF: put it online somewhere so others can benefit too.

I'd be interested to hear how others look upon this. Considering that I don't see 'my advocated practice' used in most of the code I see - not even in widely used open source projects -, I presume my stance is discutable ?
Re: Comparison operators: When equals doesn't equal equals [message #1784 is a reply to message #1449 ] Sat, 19 January 2008 12:31 Go to previous messageGo to next message
KathyReid  is currently offline KathyReid
Messages: 224
Registered: October 2006
Location: Geelong, Victoria, Austra...
Member
I was just reading this thread again and two things came to mind;

j.rf's point about whether it should be debateable to do strict comparison (===) is a good one - I'm agreeing with j.rf. If in doubt, do strict rather than loose comparison.

Also, we are having some great discussions about best practice in these thread and I'm wondering if there is a better way to consolidate them - such as a PHP best practices wiki, or handbook etc. What does everyone think?
Re: Comparison operators: When equals doesn't equal equals [message #1785 is a reply to message #1140 ] Sat, 19 January 2008 18:29 Go to previous message
lorna  is currently offline lorna
Messages: 413
Registered: October 2006
Location: Leeds, UK
Feeling Comfortable

I think there is a better way to consolidate them, but I don't know what it is! We've kicked the idea around on the IRC channel before as well, without reaching a conclusion.

Personally I think there is some really good info buried on the forums and perhaps we could expand the front-end of the site to make it all more accessible. Anyone got a response or more specific suggestion?


Lorna Mitchell (online at http://www.lornajane.net)
Previous Topic:To pecl or Not to pecl
Next Topic:Code like a Cosmo Girl
Goto Forum:
  


Current Time: Fri Jul 30 13:03:14 EDT 2010

Total time taken to generate the page: 0.01095 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.0.
Copyright ©2001-2006 FUD Forum Bulletin Board Software