That kind of thinking eventually leads to object-oriented programming. I like to remember that $GLOBALS is an object, if you want to think of it that way.
The array is actually $GLOBALS, not $GLOBALS 😉
An inconsistency in naming because the $_* style superglobals were introduced later, as I recall.
I would say that the $_* superglobal arrays act as registries for incoming variables. Consequently, it is clear that functions that access them are not designed to be reusable and have to be modified should they change. Also, since they are registries, they are isolated from normal variables, thus avoiding the variable poisoning problem posed by register_globals.
I very often find that some little hunk of info I grabbed in a function someplace has use somewhere else. A global variable makes a nice temporary van to move the data from place to place.
The appropriate mechanisms would be to have that "function someplace" return "some little hunk of info" and "somewhere else" have an appropriate parameter to accept it, or have "function someplace" place "the some little hunk of info" into an argument passed by reference, and then the caller passes the variable aliased to it and "somewhere else". That way the caller and the two functions are insulated from the others' implementation.
If you are into object based programming, it may well be that the two functions should form part of a class interface, in which case the global variable would become a member variable at object scope ("global" between member functions, if you see it that way). In that case, the private implementation of the class is insulated from the caller.
Either way, the caller only needs to know the interface (i.e., parameter list and what may be returned) provided by the functions, be they free functions or member functions. It does not have to be concerned with their implementation details, and can be sure that calling them will not unexpectedly change its own state due to an unfortunate choice of variable names. As such, they may freely change their implementation specifics without affecting the caller other than by the interface provided.
On the other hand, I've seen very complex algorithms written simply to avoid the use of the Dread Global Variable.
I do not see how the algorithms need to be more complex. The main change is how the variable enters into the current scope. Any examples?
Globals are a tool, to be used or misued. Sometimes they're the right tool for the job.
I tend to agree with that, just as I think that gotos are sometimes the right tool for the job. Indeed, the concept of a global registry is something I find useful. However, I strongly disagree with the notion that it is right to use them as a casual substitute for argument passing.