rfc:inconsistent-behaviors
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
rfc:inconsistent-behaviors [2014/02/05 03:09] yohgaki created |
rfc:inconsistent-behaviors [2021/03/27 14:31] (current) ilutov Move to inactive |
||
---|---|---|---|
Line 4: | Line 4: | ||
* Date: 2014-01-08 | * Date: 2014-01-08 | ||
* Author: Yasuo Ohgaki < | * Author: Yasuo Ohgaki < | ||
- | * Status: | + | * Status: |
* First Published at: http:// | * First Published at: http:// | ||
- | * Renamed to: https:// | + | * Renamed to: https:// |
This RFC is to discuss comparison and conversion inconsistencies in PHP. | This RFC is to discuss comparison and conversion inconsistencies in PHP. | ||
Line 25: | Line 25: | ||
Type juggling only works for INTEGER or HEX like strings. | Type juggling only works for INTEGER or HEX like strings. | ||
+ | |||
+ | Most problematic is HEX like strings being auto-coerced during | ||
+ | comparison, but using //different rules// from manual casting. That | ||
+ | is, ( 0x0A == " | ||
+ | although " | ||
+ | |||
+ | This despite http:// | ||
+ | states clearly that for number-string comparison, we " | ||
+ | strings and resources to numbers." | ||
+ | string patterns cannot be " | ||
+ | a " | ||
+ | casting for the same string. It is hard to view it is anything but a | ||
+ | bug that it does not. | ||
=== HEX === | === HEX === | ||
Line 157: | Line 170: | ||
https:// | https:// | ||
+ | |||
+ | Not only is this not a bug, it isn't even exceptional behavior on the | ||
+ | modern web. Users who find this behavior surprising are likely | ||
+ | inexperienced with MySQL -- clearly PHP's partner in server-side | ||
+ | ubiquity as part of the dominant *AMP stack -- which has the exact | ||
+ | same rules for auto-coercion of " | ||
+ | comparison context. | ||
+ | |||
+ | In MySQL (all supported versions): | ||
+ | |||
+ | <code sql> | ||
+ | SELECT CASE WHEN ' | ||
+ | </ | ||
+ | |||
+ | prints ' | ||
+ | |||
+ | There are other popular languages that follow the same | ||
+ | casting/ | ||
+ | coercion during comparison. For example, JavaScript | ||
+ | parseInt(' | ||
+ | SQLite, the ubiquitous embedded SQL database, also CAST( | ||
+ | ' | ||
+ | |||
+ | The SQLite documentation explains the logic well: | ||
+ | |||
+ | > When casting a TEXT value to INTEGER, the longest possible prefix of | ||
+ | > the value that can be interpreted as an integer number is extracted | ||
+ | > from the TEXT value and the remainder ignored. Any leading spaces in | ||
+ | > the TEXT value when converting from TEXT to INTEGER are ignored. If | ||
+ | > there is no prefix that can be interpreted as an integer number, the | ||
+ | > result of the conversion is 0. (http:// | ||
+ | |||
+ | And this behavior is not considered particularly " | ||
+ | |||
+ | Since the ubiquity of MySQL has been used to support the expectations | ||
+ | users should have of PHP, it's fair to note Oracle, SQL Server, and | ||
+ | PostgreSQL will not allow the above comparison to be performed: the | ||
+ | statement produces a fatal error. It's a runtime casting error: these | ||
+ | languages do not prohibit comparing values of different datatypes, as | ||
+ | long as the engine can cast the runtime contents of the value. Yet | ||
+ | such implementations, | ||
+ | concept, since a errant letter modifier like ' | ||
+ | error where the expectation might be to either have a ' | ||
+ | equal to 1 (as in MySQL) or fail gracefully (as in SQLite). In this | ||
+ | respect, the SQLite behavior is more balanced than that of | ||
+ | Oracle/ | ||
+ | generous, and reasonable. | ||
+ | |||
+ | With PHP and MySQL agreeing on this behavior, it is clear that | ||
+ | automatically coercing a " | ||
+ | better term) to a number via truncation is common practice on the web, | ||
+ | even if it is news to the inexperienced user. | ||
==== String decrements ==== | ==== String decrements ==== | ||
Line 216: | Line 281: | ||
===== Function/ | ===== Function/ | ||
- | ==== is_numeric | + | ==== assert |
- | https:// | + | assert() does not accept closure while it accepts functions. |
+ | < | ||
+ | php > function f() {return FALSE;} | ||
+ | php > assert(f()); | ||
+ | |||
+ | Warning: assert(): Assertion failed in php shell code on line 1 | ||
+ | php > assert(function() {return FALSE;}); | ||
+ | </ | ||
+ | |||
+ | https:// | ||
==== base_convert ==== | ==== base_convert ==== | ||
Line 225: | Line 299: | ||
https:// | https:// | ||
- | ==== assert ==== | ||
- | assert() does not accept closure while it accepts functions. | ||
- | https:// | + | ==== filter_var ==== |
+ | https:// | ||
- | ==== min() function | + | <code php> |
+ | var_dump(filter_var(' | ||
+ | var_dump(filter_var(' | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | bool(false) | ||
+ | double(1) | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== is_numeric ==== | ||
+ | |||
+ | https:// | ||
+ | |||
+ | |||
+ | |||
+ | ==== min ==== | ||
https:// | https:// | ||
This is not a bug. If one of operand is BOOL(or NULL), both operands are converted to BOOL and evaluated as BOOL. It may be good idea that document this behavior in min() manual. | This is not a bug. If one of operand is BOOL(or NULL), both operands are converted to BOOL and evaluated as BOOL. It may be good idea that document this behavior in min() manual. | ||
+ | |||
+ | **Status** | ||
+ | Documented. | ||
+ | |||
+ | http:// | ||
+ | |||
+ | |||
+ | |||
==== Return value of wrong internal function/ | ==== Return value of wrong internal function/ |
rfc/inconsistent-behaviors.1391569768.txt.gz · Last modified: 2017/09/22 13:28 (external edit)