< / >

This is a blog by about coding and web development.

PHP functions as lazy variables

Posted on in

Along with finally giving us anonymous functions, PHP 5.3 also gave us namespaces. This has been a looong time coming for PHP. Finally we can develop without polluting the global namespace! Or can we?

As it turns out, PHP namespaces only apply to classes, constants, and functions. Which means this:

    namespace foo;
    
    $bar = 1;

… sets $GLOBALS['bar'] to 1 across all namespaces, instead of just locally to foo. Sigh.

I’ve been playing with different idioms to get around this. First I tried static class variables:

    namespace foo;
    
    class data {
        static $bar = 1;
    }

    // in another namespace
    echo foo\data::$bar;

That’s pretty fugly. I don’t like having to lowercase a class name, but it would be even uglier as foo\Data::$bar. The biggest problem with this is that I also want to do this:

    namespace foo;
    
    class data {
        static $bar = new Bar();
    }

But property initializers suck in PHP, and don’t allow complex expressions. I don’t want to start adding initializer logic to the class or at the module level, so that method is out.

I ended up going with:

    namespace foo;
    
    function bar($newBar=null) {
        static $bar;
        if (!isset($bar) || isset($newBar))
            $bar = $newBar ?: new Bar();
        return $bar;
    }

    // in another namespace
    echo foo\bar()->baz;

It also allows you to pass in a new value manually, if needed. This comes in useful for unit testing:

    foo\bar(new MockBar());

I think that’s about as simple as you can get it. Bonus points: your namespace properties are now lazy loaded. new Bar() isn’t executed until the first time you call the function. If you never call it, no overhead.

blog comments powered by Disqus