80

Possible Duplicate:
php == vs === operator

An easy answer for someone I'm sure. Can someone explain why this expression evaluates to true?

(1234 == '1234 test')
Community
  • 1
  • 1
Cjueden
  • 1,200
  • 2
  • 13
  • 25
  • 212
    Because that's how PHP rolls: Like a square wheel. – Ignacio Vazquez-Abrams Aug 28 '12 at 02:26
  • 1
    @IgnacioVazquez-Abrams well, in JS 1234 == '1234', so you can't "blame" it on PHP along ;) – Nir Alfasi Aug 28 '12 at 02:30
  • 12
    @alfasin: Yes I can. The comparison in the question is *completely nonsensical*, and there's no reason it shouldn't be considered an error, even if for the programmer's sake. – Ignacio Vazquez-Abrams Aug 28 '12 at 02:31
  • 3
    @IgnacioVazquez-Abrams It's more of a programmer error than anything else, though there are likely some legitimate use cases for this sort of comparison. Calling this a language error, though; is somewhat absurd given that the `==` operator is _designed_ to do exactly what its doing in this scenario: a [type-juggling equality test](http://www.php.net/manual/en/language.operators.comparison.php). Other languages, prominently JavaScript, have the same sort of operator. Naturally, in both languages; `1234 === '1234 test'` is false, because that's the strict equality test. – Lusitanian Aug 28 '12 at 02:38
  • Not only that, I find the programmer solely responsible for not RDFM: http://www.php.net/manual/en/language.types.integer.php#language.types.integer.casting.from-other – Nir Alfasi Aug 28 '12 at 02:41
  • 20
    @Lusitanian: "... there are likely some legitimate use cases for this sort of comparison." Find *one*, I dare you. – Ignacio Vazquez-Abrams Aug 28 '12 at 02:43
  • @IgnacioVazquez-Abrams Hehehe, unlikely but I hate to make a blanket statement saying its entirely useless. – Lusitanian Aug 28 '12 at 02:46
  • 7
    @alfasin But it's *not* `1234 == '1234'` in question (which is somewhat understandable without a complex reason); here the question is about `1234 == '1234 test'` (which would be false in JavaScript, and is much less "expected" at first glance). –  Aug 28 '12 at 03:33
  • @pst It's true that the operator `==` doesn't act "as expected" when you have background in other programming languages, my example meant to show that in JS the operator `==`, like in PHP, doesn't act as expected compared with other languages. I agree that in JS it's "a bit more right", but that doesn't make it **right**, right ? ;) – Nir Alfasi Aug 28 '12 at 04:45
  • @alfasin I was merely pointing out that your first comment is irrelevant as it introduces *different* data (as well as adding in my thoughts in parenthesis). And yes, yes, I do consider "hard to get correct conditionals" a poor language design .. and let's not even get into the rationale behind functions that can return a "false value" on success and FALSE on failure .. –  Aug 28 '12 at 04:54
  • @pst I think that it's relevant, but you're entitled to think differently :) – Nir Alfasi Aug 28 '12 at 04:57
  • 2
    @pst btw, don't you think there's some kind of conflict between the idea that PHP was meant for non-programmers to be able to do things programmatically, and the need to understand `how things work` in order to use PHP ? just a thought. btw2, I'm a Java programmer, so I won't defend PHP - feel free to continue shooting, in fact, you don't have to work hard, somebody else already [*did all the work*](http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/) for you... – Nir Alfasi Aug 28 '12 at 05:14
  • @alfasin I have never heard that "programming language X was meant for a non-programmer". Such things are counterproductive at the core. There have been various attempts at "visual" / "non-programmer" program development tools (not strictly "programming languages"), but PHP is hardly one of them .. –  Aug 28 '12 at 05:20
  • @pst from the last paragraph [*here*](http://www.php.net/manual/phpfi2.php#overload): "specially for something like PHP where most of the scripts will be rather simple and in most cases written by **non-programmers** who want a language with a basic logical syntax that doesn't have too high a learning curve." – Nir Alfasi Aug 28 '12 at 05:26
  • @pst but you know what ? I totally agree with you that there shouldn't be a concept of "programming language for non-programmers". But then again, [that's like *our* opinion man...](http://www.youtube.com/watch?v=QsogswrH6ck) :) – Nir Alfasi Aug 28 '12 at 05:28
  • 8
    Right, it's always the programmers fault when they shoot themselves in the foot, even when [the language has 6 triggers, and both barrel aim downwards](http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/) – BlueRaja - Danny Pflughoeft Aug 28 '12 at 07:40
  • 2
    I love how the contextual operator '=' quickly evolved into '=='. I can live with the fact that in some scripting langs it was pushed even farther into '===' because some designer had a sense of humor:) I will be so excited when someone constructs a language where equality will be written as '====' or '====='! Who needs them anyways? :) – quetzalcoatl Aug 28 '12 at 12:27
  • 2
    @quetzalcoatl: One could say PHP needs a ==== operator. Or at least some way to always tell whether two variables are references to the same value without mangling them. :P – cHao Aug 28 '12 at 18:26
  • @BlueRaja-DannyPflughoeft I posted the same link 3 comments ago... :) – Nir Alfasi Aug 28 '12 at 20:31
  • PHP is for non-programmers? It's a complete PROGRAMMING LANGUAGE, with classes, inheritance, namespaces, etc. Just because a language is simpler, quicker to use, & cuts the fat of more complex languages, doesn't mean it's for the naive. In fact, you're actually arguing the language is for noobs because of this question, which is about how complex the language can be. I've been developing software for 15 years, including years of hardcore C & C++, and I'd take PHP anytime over C++. Anyone who wouldn't enjoys excessive work, endless debugging, and needless complexity - such as type-casting. – dallin Mar 07 '13 at 20:16
  • @IgnacioVazquez-Abrams No use for this? ANY time you store info in the database obtained from online forms this can be handy. How about the example given? The user enters a full street and you want to store the street number separately. Or the user enters $12 and you want to store just the number. There's literally a million uses for this. Sure you could use a function to strip out the characters, but the point is you don't have to! It saves time and complexity - how is that not better? This makes PHP elegant, not "for non-progammers". What next, you want to say the myVar++ is never needed? – dallin Mar 07 '13 at 20:23
  • @dallin: Both of those examples will fail, hard. "12b Anywhere Street" Not a number. "(int)'$12'" => "0" Oops. – Ignacio Vazquez-Abrams Sep 17 '13 at 14:19
  • @IgnacioVazquez-Abrams You are correct about the $12, as the string must start with a number or sign or it will return as 0. 12b Anywhere Street, however, works fine, and is a good example of a valid use for this functionality. I've also never seen a street number with a letter before. Are you sure you're not thinking of apartment number? Maybe a better question would be, can you think of a situation where this functionality would cause a problem? – dallin Sep 20 '13 at 21:35
  • I think this dates back to perl or before where strings would hold the intrinsic integer value of 0 or, if there is an integer in the beginning of the name: whatever that integer is. So "Hello world!" is 0 but "1234 Hello World!" is 1234. – higgs241 Oct 12 '13 at 12:51

6 Answers6

96

Because you are using the == (similarity) operator and PHP is coercing the string to an int.

To resolve it use the === (equality) operator, which checks not only if the value is the same, but also if the data type is the same, so "123" string and 123 int won't be considered equal.

Maxim Krizhanovsky
  • 26,265
  • 5
  • 59
  • 89
Lucas Green
  • 3,951
  • 22
  • 27
78

In PHP (and JavaScript -- which has slightly different behavior), the comparison operator == works differently than it does in strongly-typed languages like C or Java. The === operator has the behavior that you most likely expect. Below is a breakdown of the two comparison operators as they apply to PHP.

==

This operator is officially known as the "equality" operator, though that doesn't really fit the normal definition of the word "equality". It does what is known as a type-juggling comparison. If the types of both operands don't match (in your example, 1234 was an integer and 1234 test was a string), PHP will implicitly cast the operands to each others' types and test the equality of the newly-typed values as shown below:

<?php
var_dump( (int) 'hi' ); // int(0)
var_dump( (string) 0 ); //string("0")
var_dump( 'hi' ==  0 ); // bool(true)

var_dump( (int) '1hi' ); // int(1)
var_dump( 1 == '1hi' ); // bool(true)

It has a counterpart (type-juggling) inequality operator, !=.

===

The === operator, known as the "identical" operator, performs a strict check of the value and type of both operands and does not perform any implicit casts. Therefore, "0" does not === 0 and "1234 test"does not === 1234.

<?php
var_dump( '1234 test' === 1234 ); // bool(false)

It has a counterpart (strict) inequality operator, !==.

Quirks

Note that the === operator has behavior on objects that is considered strange by some. Say we have class A and variables $a and $b as defined below:

<?php
class A { 
  public $property = 'default value';
}
$a = new A();
$b = new A();

You might expect var_dump($a === $b); to output bool(true). It will actually return false. When used upon objects, the operator actually checks if both operands are references to the same object. The == operator, in this instance, works by checking the properties of the objects, so $a == $b.

PHP Manual Links

Lusitanian
  • 11,012
  • 1
  • 41
  • 38
  • 5
    Watch out: `var_dump(0 == 'abc');` gives `true` but `var_dump(0 == '1abc');` evaluates to `false` – rabudde Aug 28 '12 at 06:31
  • Note that C also does the type juggling, the only difference is that it has a smaller set of implicit casts. Comparing an `int` against a `float` will result in loss of precision, and comparing an `unsigned` against an `int` will give unexpected results if the `int` is negative. – Dietrich Epp Aug 28 '12 at 06:35
  • 3
    Note that this is not the same behavior in JavaScript. `123 == "123 asd"` returns false whereas `123 == "0123"` return true. – Ekin Koc Aug 28 '12 at 09:50
  • @rabudde because `(int) '1abc'` === 1. It's a similar case to `1234 == '1234 test'` – Lusitanian Aug 28 '12 at 11:37
  • @Lusitanian you're right. I want to give only a hint, what can happen when you don't pay attention and write your code quickly. Your example result is the same at the end, sure, but you force(!) the integer conversion. And I want to show the little special meaning of loose comparision to 0. – rabudde Aug 28 '12 at 12:26
28

When casting a string to an integer, any numeric characters up to the first non-numeric character becomes the number. Thus '1234 test' becomes 1234 because space is not a numeric character.

Thus 1234 == '1234 test'

If you want to force a string comparison, you should cast to string:

''.(1234) == '1234 test' // implicit
(string) 1234 == '1234 test' // explicit
strval(1234) == '1234 test' // procedural
Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
8

You are loosely comparing two different types of data (an integer and a string). PHP has a very detailed chart of how comparisons work in their system when using the loose comparison binary operator (==):

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

If you want to ensure that the types are also in sync, that is that they are both integers or both strings, use the strong type comparison operator (===).

Note that, when using this operator, this will also return false:

1234 === '1234'

If you are unsure of your types when comparing, you can couple the strong-type comparison with PHP typecasting:

$a = 1234;
$b = '1234';

if ($a === $b) { }            // Will not fire, as it is false
if ((int)$a === (int)$b) { }  // Will fire, as it is true
Andrew Vaughan
  • 234
  • 2
  • 6
4

The double equals will tell php to parse an int from the string. The string will evaluate to the integer 1234. Use triple equals '===' to get exact comparison.

Ray
  • 40,256
  • 21
  • 101
  • 138
3

If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically

var_dump(0 == "a"); // 0 == 0 -> true
amitchhajer
  • 12,492
  • 6
  • 40
  • 53