Global variables in WordPress
[][wordpress] In my critique of the code in WordPress I talked about the frequent use of global variables, something this I think it a bad practice. In response Owen Winkler writes that:
Global variables are used in WordPress in many places to make things simpler for a novice end-user to design. [...]
The point is that novice plugin and template designers shouldn’t have to worry about object-oriented syntax, and therefore lots of object members are put into the global scope.
It might be easy, but I still find this a poor way to pass information
around in an application. The global variables obscure the
relationship between functions. Take my example from the original
rant, the mysql2date()
function — it’s the second function (or
third, depending on whether or not you expect Gettext to be active) in
wp-includes/functions.php
.
The first line in the body declares four global variables named
$month
, $weekday
, $month_abbrev
, and $weekday_abbrev
. So this
function is obviously somehow dependent on those variables being
initialized. So the first question is: can I always call
mysql2date()
? Do I first have to call some initialization function,
or is this guaranteed to be done for me when I want to use
mysql2date()
in some plugin or template?
It’s not such a big mystery to figure out where the variables come
from: a quick grep reveals that they are defined in locale.php
. But
who takes care of including locale.php
? Another grep, and one sees
that this is done by wp-settings.php
— I guess that file is always
loaded, and thus one can be sure that $month
and the other globals
are indeed initialized before a call to mysql2date()
.
No wait! On close inspection of wp-settings.php
one sees that
locale.php
is loaded after the active plugins are loaded, and after
a call to do_action('plugins_loaded')
. So does this mean that a
plugin that attaches itself to the plugins_loaded
action cannot call
mysql2date()
? I believe it does!
In my installation I found no other references to the plugins_loaded
action, and so this could explain why this bug wasn’t found
earlier. But in any case — if the developers had taken the time to
properly document this dependency between locale.php
and
functions.php
, then the problem should never have occurred in the
first place.
This potential bug wasn’t the reason for my initial worries about the
use of global variables: I had been trying to get the Smart link
plugin working. It uses a global $comments
variable to know
which comments to process, but the comments.php
template doesn’t
define it to be global — in fact the $comments
variable is a local
variable in the comments_template()
function in
comment-functions.php
. This function includes comments.php
, and
thus $comments
has the local scope in that file. (These scope rule
games in PHP are just so annoying!)
I now see that the problem that triggered my anger against the global
variables was in fact a use of a non-global variable, expecting it to
be global. A bit ironic that I were to find a problem with a totally
different function, mysql2date()
, while initially being started by a
mistake in a plugin…