WordPress Development
PHP Global Variables in WordPress: When to Use Them (and How to Name Them)
WordPress search is full of 'php global variable' queries for a reason. Here is how globals work in snippets, what to avoid, and the naming conventions that keep sites debuggable.
April 23, 2026 4 min read Mark Ashton
- wordpress
- php
- workflow
A surprising amount of WordPress search traffic is some variant of "php global variable." Developers hit the keyword because a snippet needs to share state across two hooks — and PHP's global keyword is the first thing that looks like it works.
It does work. It also collides with core, with other plugins, and with the next snippet you paste from a gist. This is the version of the explanation we wish lived next to every snippet editor.
What a global actually is
In PHP, a variable declared at file scope is not automatically visible inside a function. Inside a callback you either pass the value in, read it from a container, or pull it from the global symbol table:
global $my_flag;imports that name into the function$GLOBALS['my_flag']does the same via the superglobal array
WordPress itself is full of globals: $post, $wp_query, $wpdb. That is historical, not a style guide. Core can get away with short names because it owns them. Your snippet cannot.
Why snippets make this worse
A theme functions.php is one file. A snippet library is dozens of files that all load into the same PHP request. Two snippets that both global $enabled; are sharing a variable whether the authors meant to or not.
Database-stored snippets make the collision harder to grep. File-based snippets at least show up in a project search — which is one reason we store SnipVault snippets on disk and document using global PHP variables in the docs.
If you activate snippet B and snippet A "mysteriously" changes behavior, look for an unprefixed global before you look for a cache bug.
Naming conventions that hold up
PHP does not enforce namespacing for globals. You have to.
- Prefix every name with a project or client slug:
$acme_vat_rate, not$rate. - Do not reuse core names. Never
global $postand then overwrite it. Read it, clone what you need, leave it alone. - Prefer
$GLOBALS['acme_vat_rate']when the variable is written in one snippet and read in another. It is uglier and therefore harder to treat as a local. - Constants for true constants. If the value never changes at runtime,
define( 'ACME_VAT_RATE', 0.2 )or a class constant beats a global. - No generic words.
$data,$args,$config,$user,$settingswill collide. They already have.
A useful house rule: if the name would be a legal CSS class without a prefix, it is too short.
When a global is justified
There are a few cases where a prefixed global is the least bad option:
- A value computed on
initthat three later hooks must read, and you do not want to hit the database again - Sharing a result between a snippet that cannot be merged yet (two vendors, two files)
- Interfacing with a legacy plugin that only exposes state via
$GLOBALS
Even then, set the variable in one snippet. Document the writer and the readers in the snippet description. If you have project workspaces, keep the writer and readers in the same project so they get reviewed together.
Better alternatives
Most "I need a global" moments are a missing API.
- A namespaced static on a small class or a function with a static variable, if the state is private to your feature
- The object cache via
wp_cache_get/wp_cache_setfor per-request or persistent memoization - A custom hook that passes the value as an argument instead of parking it in a global for someone else to remember
- A custom table or option if the value must survive the request — globals do not
- A closure bound to
add_actionif you only need to carry state into one callback
WordPress 6.9+'s Abilities API is another escape hatch: register the action with an input schema instead of leaving a mutable global for an agent or REST call to poke. We covered that in WordPress 6.9's Abilities API and custom snippets.
Globals and PHP 8.4
PHP 8.4 (fully supported by WordPress 6.8+ as of the 2026 support clarification) is stricter about dynamic properties and more vocal about implicit nullables. Globals themselves still work. What breaks is the sloppy code around them: reading an undefined global (now a warning you will see in logs), or stuffing ad-hoc properties onto objects you found in $GLOBALS.
If you are upgrading PHP this year, search snippet files for global $ and `$GLOBALS` and make sure every name is initialized before first read. A [security audit will not catch an uninitialized global, but a sandbox request on a page that exercises the snippet will.
A pattern we recommend in snippets
Keep shared state behind a single accessor so the global name appears once:
- One snippet defines
acme_get_vat_rate()which reads a default, allows a filter, and only then touches a prefixed global as a per-request cache - Every other snippet calls the function
That gives you a grep target, a filter for tests, and a place to add instrumentation when the rate is wrong in production.
What not to do
- Do not store unsanitized
$_GETor$_POSTin a global "for later." Sanitize at the boundary, then store the clean value. - Do not use a global as a feature flag you toggle from the front end. Use an option or a capability check.
- Do not copy a Stack Overflow snippet that starts with
global $wpdb;and concatenates SQL.$wpdb->prepareexists. - Do not name a snippet-level variable
$wp_query"temporarily."
Globals are not evil. Unprefixed, undocumented, write-from-anywhere globals are how snippet libraries become haunted. Treat them like a public API — because in a shared PHP request, they are.