Typed PHP, Stronger Types for Cleaner Code (2014)
Native Function Inconsistencies
PHP is often decried because of the inconsistencies in the native functions. PHP is often praised because of the quality of the documentation. These are related! The documentation has evolved so well because native PHP functions are inconsistent.
This section is going to make me sound like a PHP-hater. That couldn’t be further from the truth! I love PHP and I’m committed to using it and helping others use it. To know what we’re building, we have to know what we’re trying to avoid building. That’s the point of what’s to follow.
These functions are described at http://php.net/manual/en/ref.strings.php
The full list contains 98 functions, 30 of which use one or more underscores. Sometimes functions clearly composed of multiple full words (like setlocale) don’t have underscores. Sometimes functions which do almost exactly the same things (strlen vs. str_word_count) are handled differently.
Most of the string functions use abbreviations of some kind. Applied consistently, this wouldn’t be a problem. However, the inclusion of a few non-abbreviated functions makes the string API difficult to memorise, which often means a round-trip to the documentation.
Inconsistent Argument Order
· array_key_exists($needle, $haystack)
· stripos($haystack , $needle)
The natural order of arguments differs depending on whether you are working with array functions or string functions. Rasmus explains this as a result of keeping as close to the underlying C libraries as possible. The problem with this explanation is that it means nothing to developers who have never worked with C, and just want to work with PHP.
It’s helpful to remember that the array methods are needle/haystack and the string methods are haystack/needle.
Regular Expression / Strings
In PHP, Regular Expressions are represented as strings but handled with a completely different set of functions. That’s just strange. While I can accept that Regular Expressions have a similar representation to strings, and that the functions they are given to (in the C libraries) expect to work with strings, developers shouldn’t need to account for this.
PHP assumes a string is a Regular Expression, if it starts and ends with recognisable delimiters. You can learn more about that at http://www.php.net/manual/en/regexp.reference.delimiters.php.
1 "abc".replace("b", "123"); // "abc" becomes "a123c"
2 "def".replace(/[e]/, "456"); // "def" becomes "d456f"
These languages make clear the distinction between strings and Regular Expressions.
Nouns / Verbs
Some of the native functions are verbs (like echo and parse_str) while others are nouns (like htmlentities and soundex). This makes it tricky to reason about what the method is doing.
Strange Return Values
Many of the native functions return multiple types. In the case of strstr a string is returned if it is matched, else the function returns false.
In contrast to this, the preg_match function returns 1 if the pattern is found, 0 if it is not and false if an error occurred. This makes for a slew of type checking before any of the return values can be used for their intended purpose.
PHP is a great language.
But if you’ve worked much with PHP, you will either have grown to ignore the sad state of PHP’s scalar type handling, or been frustrated at the lack of good alternatives.
And for most small-to-medium sized projects, adding a revised type-system is unnecessary. Yet if you learned how to make (or even just use) a well-built type system, wouldn’t it make sense to use it in large projects? Or in any projects you cared enough about?
This area of PHP often chases developers into prettier languages. Don’t be one of those developers! Learn how to write cleaner code, by using a clean abstraction.