How to set and use global variables? Or why not to use them at all

UPDATE: My original question has been solved, but this is turning into a valid discussion about why not to use global variables, so I am updating the question to reflect that. The solution was <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?> as @TomJNowell suggested.

UPDATE 2: I now have it doing exactly what I wanted. But I’m still using global scope and would be happy to find a better way.

I am trying to set up a whole bunch of global variables for the permalinks to categories to be used in various places in my theme. The main reason for this is for use in both the main navigation, as well as in a series of sub navigations that are chosen based on what category the current post is in. This is not a theme I will be releasing for use by others, but is built for one very specific purpose.

This is how I am currently creating them (I’ve only pasted in a few of the variables).

function set_global_nav_var()
{
    //proposal
    global $prop;
    // Get the ID of a given category
    $category_id_prop = get_cat_ID( 'proposal' );
    // Get the URL of this category
    $category_link_prop = get_category_link( $category_id_prop );
    $prop = '<a href="' .esc_url( $category_link_prop ). '" title="Proposal">Proposal</a>';

    //Calvinball
    global $cb;
    // Get the ID of a given category
    $category_id_cb = get_cat_ID( 'calvinball' );
    // Get the URL of this category
    $category_link_cb = get_category_link( $category_id_cb );
    $cb = '<a href="' .esc_url( $category_link_cb). '" title="Calvinball">Calvinball</a>';
}
add_action( 'init', 'set_global_nav_var' );

I can now do <?php global $prop; echo $prop; ?> int he 4 places that goes and get back the whole link for the code. When that changes I only need to change it in one place. I’m open to alternatives that do not involve the global scope.

4

While I strongly advise against this, and it will not speed things up, your usage is incorrect.

WordPress already caches these things in the object cache/memory so it doesn’t have to fetch it multiple times in the same request, you don’t need to store the result and reuse, WP does that already out of the box.

It’s very likely your code is running slower as a result of this micro-optimisation, not faster!

How To Use Globals

When you try to use a global you must specify the global keyword first. You have specified it here when defining its value, but outside of that scope it needs to be redeclared as a global scope variable.

e.g. in functions.php :

    function test() {
        global $hello;
        $hello = 'hello world';
    }
    add_action( 'after_setup_theme', 'test' );

In single.php, this will not work:

    echo $hello;

Because $hello is undefined. This however will work:

    global $hello;
    echo $hello;

Of course you should do neither. WordPress already attempts to cache these things in the object cache.

Disadvantages and Dangers of Global Variables

You will see no speed increase from doing this ( you may see a tiny speed decrease ), all you will get is additional complexity and the need to type out a lot of global declarations that aren’t necessary.

You’ll also encounter other issues:

  • code that’s impossible to write tests for
  • code that behaves differently every time it runs
  • clashes in variable names from a shared name space
  • accidental bugs from forgetting to declare global
  • a complete lack of structure to your codes data storage
  • and many more

What Should You Use Instead?

You would be better off using structured data, such as objects or dependency injection, or in your case, a set of function.

Static Variables

Static variables aren’t good, but think of them as the slightly less evil cousin of global variables. Static variables are to global variables, what mud covered bread is to cyanide.

For example, here is a means of doing something similar via static variables e.g.

    function awful_function( $new_hello='' ) {
        static $hello;
        if ( !empty( $new_hello ) ) {
            $hello = $new_hello;
        }
        return $hello;
    }

    awful_function( 'telephone' );
    echo awful_function(); // prints telephone
    awful_function( 'banana');
    echo awful_function(); // prints banana

Singletons

Singletons are like static variables, except the class contains a static variable with an instance of that class. They’re just as bad as global variables, just with different syntax. Avoid them.

WP_Cache, The Thing You Tried to Do But WP Already Does It

If you really want to save time by storing data somewhere to re-use, consider using the WP_Cache system with wp_cache_get etc e.g.

$value = wp_cache_get( 'hello' );
if ( false === $value ) {
    // not found, set the default value
    wp_cache_set( 'hello', 'world' );
}

Now the value will get cached for the life of the request by WordPress, show up in debugging tools, and if you have an object cache it’ll persist across requests


Sidenote 1: I would note, that some people try to persist data in global variables across requests, unaware that this is not how PHP works. Unlike a Node application, each request loads a fresh copy of the application, which then dies when the request is completed. For this reason global variables set on one request do not survive to the next request

Sidenote 2: Judging from the updated question, your global variables give you no performance gain at all. You should just generate the HTML as and when you need it and it would run just as fast, perhaps even a tiny bit faster. This is micro-optimisation.

Leave a Comment