28 ms·
When I read the new PHP spec, I threw up in my mouth after I saw that empty("0") was a special case of empty that returned TRUE. I know that's how PHP normally
by webkike 12y ago
When I read the new PHP spec, I threw up in my mouth after I saw that empty("0") was a special case of empty that returned TRUE. I know that's how PHP normally works, but that doesn't really make my mouth taste any better.
- wvenable 12y agoThe thing you have to understand about PHP, is it's meant to easily work in a world where every value is in a string. You get strings from the browser, you get strings from the database, and strings from the file system. It was expected that these strings contain numbers and that you should be able to rationally use them as numbers without conversion. So "10" > "5" returns true in PHP where as that would be false in most other languages. The underlying representation of the value (sequence of characters, 2s compliment binary, or IEEE 754 double) means nothing in PHP; they are all supposed to be equivalent. So "12", 12, and 12.0 are the same and "0" and 0 are the same. The consequence of this design ripples through to every aspect of the language. And it ripples down to the implementation of empty. Empty(0) is true. So therefore Empty("0") is also true. The fact that one is an integer and the other is a string is not a distinction that exists in PHP. It's super weird and unexpected but it's not illogical given the rules of the language.
- leeoniya 12y agowhat threw me personally about empty() is that it doesn't invoke magic getters: "__get".
- wvenable 12y agoThat's not true, empty() will call __isset() first, and only if it returns true will it call __get(). This is because empty() is the compliment to the isset() function. There is no reason to use empty() over the not (!) operator unless there is the potential your property doesn't exist.
- leeoniya 12y agoah, good to know. thx.
- hrktb 12y ago> There is no reason to use empty() over the not (!) operator unless there is the potential your property doesn't exist. I think empty() is one of the "magic" parts of php that requires to know what it does really really well before trying to use it, especially before 5.5. For anyone learning the language, avoiding empty() altogether might be best/ One of the most interesting thing IMO is the suppression of any error occuring during the test. I.e "empty($object->is->null->but->we->call->nine->levels->of->properties)" won't generate any warning nor exception about calling properies on a null object, it just returns "true". It's powerful, while being a potential trap for anyone not aware of this behavior.
- chriswarbo 12y ago> You get strings from the browser Really? I thought browsers sent HTTP requests. > you get strings from the database Really? I thought databases returned tables, ie. ordered collections of rows with individually-typed columns. > and strings from the file system. Really? I thought filesystems returned streams of bytes. Just because lots of values can be represented by strings, doesn't mean they are strings. "X is a string" is the cause of: * XSS vulnerabilities: "HTML is a string" and "user input is a string"; why not concatenate them? * SQL(/shell/eval/etc.) injection vulnerabilities: "SQL queries are strings" and "user input is a string"; why not concatenate them? * Multilingual issues: "byte streams are strings" * Malformed requests/responses (ie. 'message not understood', invalid markup, etc.): "requests/responses are strings" I know you're stating the rules of PHP, rather than a personal opinion, but I think it's important to reiterate this point whenever "x is a string" comes up. Strings are an implementation detail which should be abstracted over. After all, strings themselves are just an abstraction over bytes/words. http://c2.com/cgi/wiki?StringlyTyped http://c2.com/cgi/wiki?StringlyTyped
- wvenable 12y agoMuch of the reasons for PHP being stringly typed are historical. For example, extremely old database drivers used to stringify everything so you didn't get individually-typed columns. An HTTP request, specifically an encoded GET or POST, all values from the browser are strings. A file system is a stream of bytes, but many common web file formats stringify all values (JSON, XML, INI, etc). > Strings are an implementation detail which should be abstracted over. That's exactly what PHP does -- PHP doesn't care what representation a value has. But that is also then the source of it's strangeness.
- chriswarbo 12y ago> > Strings are an implementation detail which should be abstracted over. > That's exactly what PHP does -- PHP doesn't care what representation a value has. But that is also then the source of it's strangeness. I don't know if that's a valid use of the term "abstract", but it's certainly not what I meant. Rather than passing around low-level values for as long as possible, and only interpreting their contents when forced to (eg. when "+" forces them to be treated numerically); instead, I meant interpreting values as soon as possible so that they're treated as the appropriate type. > An HTTP request, specifically an encoded GET or POST, all values from the browser are strings. Again, they're only represented as strings. When I use an "order" parameter in my application, I want it to be an Order. I don't want it to be NULL. I don't want it to be a string which may-or-may-not be the numeric ID of an Order which may-or-may-not be stored in my database. If it's not an Order (eg. if the "readOrder" function I declared as the handler for this parameter returned [] instead of [$the_order]), the request is malformed so a HTTP 400 response should have been sent. My application should never even start if the data it needs isn't available. Of course, that's exactly what "dependency injection" is in the OOP world; it's also a major use-case for the Reader monad in the Functional Programming world.
- rmrfrmrf 12y agoEDIT: Brain fart; don't use this. See comments below. Just use the following if you really want to account for strings containing the number 0. (!isset($var) || $var === false); Note the triple equals sign.
- arenaninja 12y agoThis won't work. Both 0 (numeric) and '0' (string) == false, but never === false (because when you === you're checking that it's the same type). If you expect a string '0', simply check strlen($str) > 0. If the value could be numeric, use a (string) cast.
- rmrfrmrf 12y agoYou're right; my bad. I'll edit if possible.
- wvenable 12y agoIf you really want to test for empty strings where $a is defined just use: if ($a == "") { ... } Empty is merely the function equivalent of the not (!) operator. The semantics are exactly the same except for the handling of undefined variables. It's not something one should use except if you're expecting to deal with undefined variables.
- chriswarbo 12y ago> Empty is merely the function equivalent of the not (!) operator. Nope! "empty" is an operator too: var_dump(array_map('empty', [null, '', 5, false])); PHP Warning: array_map() expects parameter 1 to be a valid callback, function 'empty' not found or invalid function name NULL See https://bugs.php.net/bug.php?id=66368 https://bugs.php.net/bug.php?id=66368
- jacquesm 12y agoThat should teach me to read HN while eating.