PHP pains

Filed under: JWRD, Software — Jacob Welsh @ 21:00

Because who knows, maybe the web hasn't quite yet overflowed with PHP bashing.

I was already well aware that PHP does just about everything the stupid way and is out to get me at every juncture. This goes doubly so for its fans, or at least the noisier ones with ever-ready and search-engine-friendly supply of "helpful" tips, tutorials and example code. It's one of those things that I continue using not because it's good but because it works at all, and the manageable costs of using it are still outweighed by the largely unknown costs of replacing it. It has a certain maturity coming from heavy use in practice, occupying that ecological position earned by having been in the right place at the right time to enable Linux to become an economic force in the first place.

Against this backdrop, my chief annoyance with it on a recent foray has been that the documentation is sorely lacking in crucial details, and sometimes even outright misleading; and the situation is compounded by a lack of sufficient cross-referencing to where related information might be found. Traversing one branch of the tree you'll find one thing, while on another branch, if lucky or persistent enough to stumble on it, you may find what seems to say the opposite on the same topic, with no reference to the first. In all, it strikes me more as just another collection of tips and tutorials than any systematic attempt to specify what things are or what they do.

For one simple example, how do you end a segment of PHP code embedded in an HTML document, that is, what is the so-called closing tag? Okay, so if you've ever seen any PHP code it's obviously ?>, but the manual illustrates it with whitespace in front. Is that required? (Testing suggests "no".) And what becomes of the trailing newline when the closing tag comes at the end of a line?

If a file contains only PHP code, it is preferable to omit the PHP closing tag at the end of the file. This prevents accidental whitespace or new lines being added after the PHP closing tag, which may cause unwanted effects because PHP will start output buffering when there is no intention from the programmer to send any output at that point in the script.

Can I be forgiven for taking this to mean that the newline would be copied to the output, just like any other character outside the magic tags? Because that's incorrect; rather, under Instruction separation - a topic which doesn't logically have much to do with tags - they let it slip that "the closing tag for the block will include the immediately trailing newline if one is present." And by "include" they indeed mean that it will NOT be copied into the output. So that whole "it is preferable to omit" business doesn't mean there's any real need to omit, just that PHP users are assumed to be too sloppy not to leave excess trailing whitespace in a file, and in a context where such excess would matter. How very helpful: for my pains of reading the manual I am very nearly rewarded by being made duller.

For another simple example, what is the scope of those variables that come into being as function arguments, and in particular is it OK for them to shadow the names of global variables?(i) The User-defined functions page has nothing to say on the matter. Neither does Function arguments. Surely Variable scope, then? Not exactly; that only covers variables accessed or assigned within the function body, although it does kindly remind me of the derangement whereby global variables can't even be read from within a function without explicitly importing them.(ii)

I suppose then it's little wonder that PHP people don't tend to bother with functions anyway and just paste things all over the place; and I'm stuck with empirical testing, searching the rumor engines, and hoping for the best.

  1. If you find me paranoid to consider that the scope might not be properly local, note that functions defined inside other functions are NOT local! And what happens if such an inner function, when globally invoked, accesses variables defined locally in its containing function? I'm not sure I even want to know. [^]
  2. This evidently proved such a pain in practice that they had to introduce... SUPERglobals! A mechanism so special that it applies only to specific built-in things and certainly isn't to be used by lowly "user-defined" code. [^]


  1. A nice example of the "manual" talking straight nonsense:

    If buffer is 0 then write operations are unbuffered. This ensures that all writes with fwrite() are completed before other processes are allowed to write to that output stream.

    Otherwise, some things that we learn can't be done reliably in php:

    • Getting random bytes from the OS (random_bytes requires v7)
    • Opening a file such as /dev/urandom without buffering (the 'read' counterpart to the above requires v5.3.3)
    • Opening a file at all (thanks fopenwrappers)
    • Getting the length of a string (thanks mbstring.func_overload)
    • Creating a new session (i.e. new identifier) without touching any that might exist at the current identifier
    • Loading a session if one exists, without creating a new one

    Basically, you're required to think like a monkey in order to get anything done here.

    Comment by Jacob Welsh — 2024-03-29 @ 18:43

  2. There was a "direct IO" but it was removed in 5.1.0 because "In all other cases, the standard filesystem functions are more than adequate."

    The interactive shell mode (php -a) doesn't work, even when built with readline support (as confirmed by php -m).

    Comment by Jacob Welsh — 2024-03-29 @ 18:56

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by MP-WP. Copyright Jacob Welsh.