From Pin Eight
Revision as of 22:56, 28 November 2020 by Tepples (talk | contribs) (Remaining issues: Chained ternaries are deprecated in PHP 7)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

This is a mini-rant, a short essay refuting a common misconception among users of an Internet forum. If you think this essay is FUD, feel free to explain why on the essay's talk page.

Some problems with the PHP programming language are solvable by applying a few coding standards. But others remain painful. I've read the articles "PHP: a fractal of bad design" by Eevee and the "Hardly" rebuttal by ManiacDan. (There are also rebuttals by Jakub Vrána[1] and Dino Beslagic[2]) A lot of these articles about the merits of PHP make inconsistent points. So I'll keep this short so that any inconsistencies can be found and corrected.

Coding standards

JavaScript has plenty of warts, such as the behavior of == vs. ===. Douglas Crockford's JavaScript: The Good Parts lays out some coding standards that reduce the mental load of programmers producing new code. Just as in JavaScript, there's a smaller elegant language within PHP struggling to get out, especially since PHP version 5.4. Similar standards could be laid out for PHP.

Convert errors to exceptions
PHP has two parallel error reporting mechanisms: the "error" system and the "exception" system. You can handle both by using the error handler snippet at the top of the manual page for the ErrorException class. This snippet converts errors that aren't silenced (operator @) to exceptions. It also changes the behavior of the silence operator to act not unlike an inline try for functions that use the "error" system.
Forget == exists
Use only ===. In those cases where you want loose comparison, explicitly cast both sides of each expression to the type as which you want to compare them. This way you have to memorize only the casting rules, not the (different) rules for comparison as well, and don't end up inadvertently treating different hash values as equal.[3]
Some php.ini options are not for deployment to production
These include scream.enabled.
When doing things related to a database, use methods of your connection object
This way, you avoid the real mess. For example, if $db is a database connection object, you can use $db->quote (for PDO) or $db->escape_string (for MySQLi) with statements that cannot be prepared and bound the normal way because they are variadic (especially statements using operator IN).
Use PDO for SQL databases
The way the PDO library handles prepared statements makes Bobby Tables-type injection errors easier to avoid than older database client libraries. For example, it allows passing parameters to a prepared statement as an array with numeric or string keys instead of positional arguments to a bindParam() command, which makes variadic statements possible.
Don't try fopen() on URLs with an Internet scheme
This is non-portable, as it's one of the things server administrators routinely turn off for security reasons when your application shares a server with someone else's. Instead, use the CURL library for URLs.

Remaining issues

In this Slashdot post I mentioned six actual problems with PHP 5, and I later added another.

  • Number-like comparison of strings can never be fully turned off. For example, both '10' <= '1e1' and '10' >= '1e1'. One can use strcmp in one's own code and pass sort_flags to sorting functions that support them, but some functions still use the built-in operators < and > that don't even impose a total order. Likewise, switch uses the built-in == comparison operator whose semantics are byzantine.
  • Parse errors and undefined function errors are fatal in PHP 5.
  • Inconsistent conventions for function naming and argument order in the standard library.
  • Associativity for the ternary ? ... : operator is the less useful side.
  • PHP allows the server operator to change program semantics in ways that are annoying to work around, especially for shared hosting subscribers without access to the server-wide configuration. At various times, these have included "magic quotes" that spray backslashes all over the request variables, not following HTTP redirects in the CURL library,[4] and restricting the size of files uploaded by a site's users to outdated limits such as 2 megabytes by default.
  • PHP versions change the semantics of existing programs in ways that encourage shared hosting providers to continue to offer only outdated versions of PHP, making it impossible for web application developers to take advantage of new features. Compare Python, which puts added functions in one namespace per module and conditions new incompatible syntax features on presence of from __future__ statements.
  • The developers of PHP rejected keyword arguments prior to PHP 8.[5]

Changes in PHP 7 diminish these somewhat:

  • The grammar has been cleaned up.
  • Scalar type hints for function arguments and returned values make it less likely that you'll hit a loosely-typed comparison in the first place.
  • The null coalesce operator $a ?? $b acts like $a !== NULL ? $a : $b, except its associativity is on the correct side so that it can be chained properly: $a ?? $b ?? $c behaves like SQL COALESCE(a, b, c).
  • Many fatal errors have become engine exceptions, much as Python has ImportError and NameError exceptions that the caller can catch.
  • A bunch of the poorly thought out duplicate functionality is gone.
  • Chained ternary operators are deprecated for removal in PHP 8.

But just as importantly, PHP 7 also guarantees that the significant language improvements in 5.4, 5.5, and 5.6 are present, as opposed to the outdated PHP 5.3 included with RHEL 6.x and CentOS 6.x.

  • Array syntax improvements: [1, 2, 3, 4], foo()[0], foreach ($array_of_arrays as list(...)) { ... }
  • yield
  • finally
  • Array packing and unpacking of positional function arguments: function variadic($first_arg, ...$other_args) and bind($type_strings, ...$argument)
  • Omnipresent short echo syntax <?=
  • Exponent operator: 3 ** 2 == 9 && 2 ** 3 == 8
  • "Magic quotes" and "safe mode" are gone in 5.4
  • The cURL library follows HTTP redirects safely since 5.5.3


  1. Jakub Vrána. "PHP: a fractal of not so bad design". Accessed 2019-11-13.
  2. Dino Beslagic. "PHP hammer: not a fractal of bad design". 2012-07-10. Accessed 2019-11-13.
  3. One example shared by Hazardius on Twitter is md5('240610708') == md5('QNKCDZO') because they both begin with 0e, which in floating-point notation means "0 times 10 to some power".
  4. From March 2005 through September 2013, cURL could not follow redirects with open_basedir enabled because of a heavy-handed security fix.
  5. Brent. "What's new in PHP 8"., 2020-11-26. Accessed 2020-11-28.

External links