In PHP: 1234 == 001234

Ran into a PHP problem this morning, and Olle helped me find a workaround, so I thought I should publish here for the benefit of others.

If you are comparing two values in PHP — let’s say a password that a user has entered and a password that it stored in a database. In most cases you can compare them like this:

if ($password_from_users == $password_in_database) {}

But — and here’s the problem — if the two values you are comparing both look to PHP like they are numbers, PHP will compare them as numbers even if they “look different.”

For example, if you are comparing 1234 with 001234, PHP will consider them to be “equal” if you compare them as above.

This is because PHP is “too smart for its own good” and “helpfully” converts all integer-like strings to integers for comparison purposes (as explained here: “If you compare two numerical strings, they are compared as integers”).

The simple solution:

if (“s” . $password_from_users == “s” . $password_in_database) {}

By prepending a string (“s”) to each side of the comparison, PHP is prevented from helpfully converting the string to integers, and the two are thus deemed not equal as they should be.

Thanks for the help, Olle.

Comments

Rob L.'s picture
Rob L. on December 8, 2005 - 16:38 Permalink

So you can prepend it with anything you want, right? Doesn’t have to be “s” or “string”, but could be something less staid, like “whoooopeeeeee” or “BLAM!”, am I correct?

Isaac Grant's picture
Isaac Grant on December 8, 2005 - 17:30 Permalink

You could also just use the === comparison evaluator, which checks value and type, and to my opinion a bit cleaner.

if ($password_from_users === $password_in_database) {}

Charles's picture
Charles on December 8, 2005 - 19:49 Permalink

Or, the more language agnostic way (works in most C inspired shell scripting languages):
if (!strcmp($password_from_users, $password_in_database) { login(); }

Charles's picture
Charles on December 8, 2005 - 22:15 Permalink

I forgot a bracket. I’m useless without my syntax highlighting. :( Time to go apply for a job in management…

if (!strcmp($password_from_users, $password_in_database)) { login(); }

Olle Jonsson's picture
Olle Jonsson on December 9, 2005 - 11:21 Permalink

The one and only positive thing I have to say about my top-of-my-head suggestion to Peter is that the === operator was introduced in PHP4. (Where would that code be when trying to run on those near-ubiquitous PHP3 servers, huh?)

But strcmp really is a mainstay since the v3 days.

In the user-contributed notes on that page, my pessimistic approach to PHP’s type system is given some happier information to use. Among the commenters, Mr Radovanovic (with a Dutch email) says it most tersely: “That’s why we should use strcmp or === (checks type also), for string comparisons.”

Matt's picture
Matt on December 17, 2005 - 18:22 Permalink

I think you could also do it with a cast:

if ((string) $password_from_users == (string) $password_in_database) {}

This makes it very clear what you are doing.

Peter Rukavina's picture
Peter Rukavina on December 17, 2005 - 20:38 Permalink

Matt, I tried that, and it didn’t work.

Isaac Grant's picture
Isaac Grant on December 17, 2005 - 22:19 Permalink

Casting doesn’t work, as php starts from the standpoint that 001234 is a number, and hence, drops the first two zero’s before switching it to a string. Not sure why this is — just one of those weird little things in php type handling.