Edit report at https://bugs.php.net/bug.php?id=43304&edit=1

 ID:                 43304
 Comment by:         michael dot kluge at wundermedia dot de
 Reported by:        ken at smallboxsoftware dot net
 Summary:            Casting During Comparison
 Status:             Open
 Type:               Feature/Change Request
 Package:            Feature/Change Request
 Operating System:   ALL
 PHP Version:        5.2.5
 Block user comment: N
 Private report:     N

 New Comment:

Well, this is what we do.
But this is in my opinion nothing but a workaround for that.

I would regard the current behaviour as a bug or, sadly, rather as an example 
of bad design in any language. It's just not logical.

Javascript e.g. implements this correctly (from Firebug; Mozilla 
JS-implementation):
>>> var x1='001',x2='01';
undefined
>>> x1==x2
false
>>> x1===x2
false
>>> x2=1
1
>>> x1==x2
true
>>> x1===x2
false

Therefore I added my last comment to (re-)start a discussion on that, hoping 
that this might be changed or at least be made configurable. 
At least this request is marked as "Feature/Change Request". ;-)

My idea is to change this:
- Drop the concept of "numerical strings"
- Equal types do never convert on any comparison

First this should be made configurable (default is to stop the weird 
behaviour), to give grace time to the developers to adapt their scripts
In later versions this should be removed completely.
Maybe a similiar way the magic-quotes-crap is going...

Maybe one more thing about the docs:
It states:
"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."
This also constricts the simple declarations of the operators in the case of 
both operands being "numerical strings".
This is exactly the behaviour being very bad in my eyes, and should be changed 
for creating unexpected results in certain circumstances.
I see no valid reason for the operators to change behaviour if both operands 
are of the same type.
(Except maybe lazy devs not willing to obey types) ;-)

Maybe I've overseen something... Does anybody know of any good reason why the 
actual behaviour might be regarded better than the one proposed by others and 
me?


Previous Comments:
------------------------------------------------------------------------
[2012-01-16 15:53:25] delphists at apollo dot lv

>From docs:
[quote]
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.
[/quote]

Want to be strict, when comparing? Then use strict operators...

------------------------------------------------------------------------
[2012-01-16 14:29:07] michael dot kluge at wundermedia dot de

No comments from any PHP devs yet?

Well I strongly disagree with the current implementation.

>From PHP-Docs:
$a === $b Identical TRUE if $a is equal to $b, and they are of the same type.

This is the correct definition of the === operator.
An so it should work like that definition:

So
$a = "001234";
$b = "1234";
$a == $b should be equal to $a === $b (both should be false)
as both variables hold the same type
and from the above definition
those expressions should be equal:
$a === $b
($a == $b && typeof($a)==typeof($b))

So if (typeof($a)==typeof($b)) is true, $a===$b should be identical to $a==$b.

If comparing two variables of the same type in NO case any type-conversion 
should be applied!

If you need conversions in those cases these should be explicitly noted as e.g.:
intval($a) == intval($b)

Adding special exceptions to the general definition doesn't make much sense in 
my eyes; it just makes the base definition wrong in certain circumstances and 
leads to unexpected behaviour in certain cases (see comment from kissifrot).

We stumbled upon this when comparing certain product ids in use by one of our 
customers, just being different in the leading zeros. (So id "001" is another 
product than "01" ==> therefore using strings; please don't ask why, as I don't 
know what reasons might have caused these strange ids)

delphists said that "there are also lots of cases when numerical strings have 
to be compared as integers". I agree with that, but in those cases the 
developer should convert the types manually.
Also the example with the database should, in my opinion, be implemented 
differently:
The model should return integers for integer-typed database fields and not 
strings.
On the other hand if you expect input parameters containing integer values 
these could also be converted to integers, which can be easily done in the 
validity checks of the parameters.

IMHO, despite of PHP trying to make type-conversions transparent to the 
developer, the developer should in any case keep in mind, that PHP is not 
typeless and respect the types accordingly. And "0123" and "123" are definitely 
NOT logically equal in any case! I think the weird concept of "numerical 
strings" should be dropped.

------------------------------------------------------------------------
[2011-03-11 09:43:13] delphists at apollo dot lv

Sorry for digging up this bug report, but it's still opened, so I don't think 
that digging it up should be a problem.

I agree with kissifrot about specific case - both values convert to 
"(int)2147483647", at least on 32bit system, which is nowhere near to 
"00001000010000000198358".

Though, I can't agree with drm. There is a reason for having two types of 
comparisons - if you are sure that you don't need values to be converted, just 
use strict comparison.

I agree that there are cases when numerical strings need to be compared as 
strings, but there are also lots of cases when numerical strings have to be 
compared as integers. For example, some functions that return data from DB, 
return integers as strings, which may be compared to data from browser, which 
by default is also string, but comparison needs to work like if they were 
numbers.

------------------------------------------------------------------------
[2011-02-17 08:58:37] kissifrot at gmail dot com

I agree with that, for example if I have
$ric1 = '00001000010000000198358';
$ric2 = '00001000010000000198455';
var_dump($ric1 == $ric2)

should return false, not true, just because it's logical.
But the current behavior makes PHP somewhat unreliable :(

------------------------------------------------------------------------
[2008-09-06 23:49:58] drm at melp dot nl

Though documented (http://www.php.net/language.operators, quote "If you compare 
two numerical strings, they are compared as integers."), this is indeed 
unexpected behaviour (and thus a bug)

This bug will probably be closed and denoted as "sorry, documented feature", 
but I think this is really a candidate for revision in any next major PHP 
version.

Comparison should always feel intuitive, and PHP has made the move towards more 
"secure" defaults. This falls (imo) under the same category. Please witness 
following example.

client side code:
<form ...>
   <input type="radio" value="0" name="selection" /> No selection
   <input type="radio" value="whatever" name="selection" /> whatever selection
   (...)
</form>

server side code:
if ( $_GET['selection'] == 0 ) {
   echo '<p>Please make a selection!</p>';
} else {
   // process request
}

Though the example does not imply any security issues, they are not 
unimaginable. Please reconsider the behaviour of the comparison operator.

My suggestion:
Implement (and document!) the following:
Any left side of the comparison is only cast to number if the right side 
doesn't fail to. Casting to number is considered successful, if and only if the 
string would syntactically be a number in the PHP
Therefore, the string should match the following:

http://php.net/language.types.integer 
http://php.net/language.types.float

[At both pages, see the "formal" definition of both types.]

In any OTHER case, the comparison should act as follows:
If ANY of the sides is of a string type (and of course fails to cast to 
number), the other side is cast to string, causing the types to follow these 
rules:

integer: the string representation of the integer (e.g. "0", "-4" or "123")
float: the string representation of the floating point number, represented in 
one and only one particular format, preferably just the %.f format.
boolean: cast to integer, cast to string (so true becomes 1, becomes "1"; false 
becomes 0 becomes "0")
array: "array" causing a notice
object: "object" causing a notice, or calling the __toString method if defined.

The oppposing problem is a non-generic way of handling any other comparison. As 
a rule, we could state that any other comparison -if both sides of different 
type- is handled the way it is in the current PHP version. If they are of the 
same type, the == operator should act the same as the === operator.

This is, as i am very sure, easily realized. 

Please do not hesitate to ask me any questions through mail.

------------------------------------------------------------------------


The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

    https://bugs.php.net/bug.php?id=43304


-- 
Edit this bug report at https://bugs.php.net/bug.php?id=43304&edit=1

Reply via email to