ZF-1378: Setting "lazy" objects in registry

Description

One thing I was missing in Zend_Registry is sharing a single instance between several application classes, without having to create the instance in a central place. Zend_Registry helps with the sharing part, but we don't want to create an instance if it isn't needed. My solution was to extend Zend_Registry with a new method setLazy(), but this could be useful to others, so maybe it could be added to Zend_Registry.

My current solution works like this:


<?php
// init
require_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();

// test class
class TestClass {
    function __construct($x, $y) {
        echo "$x * $y = ", $x * $y, "\n";
    }
}

// a minimal extended class, stuff like checking if index is taken et  cetera missing
class My_Registry extends Zend_Registry {
    private static $_lazyRegistry = array();

    public static function get($index) {
        if (!self::isRegistered($index) && isset(self::$_lazyRegistry[$index])) {
            $object = call_user_func_array(
                array(
                    new ReflectionClass(self::$_lazyRegistry[$index][0]),
                    'newInstance'
                ),
                self::$_lazyRegistry[$index][1]
            );
            self::set($index, $object);
        }
        return parent::get($index);
    }

    public static function setLazy($index, $class) {
        self::$_lazyRegistry[$index] = array($class, array_slice(func_get_args(), 2));
    }
}

// normal set, constructor is called here
My_Registry::set('test1', new TestClass(3, 14));

// new, lazy set, everything after the second parameters are  parameters for the constructor
My_Registry::setLazy('test2', 'TestClass', 9, 6);

var_dump(My_Registry::get('test1'));
// constructor for test2 is called here
var_dump(My_Registry::get('test2'));
var_dump(My_Registry::get('test2'));
?>

Comments

Assigning to Bill Karwin.

Very good idea! Thank you for the code snippets.

This is a really cool idea, but I think it qualifies as an advanced usage that most people do not need. I would be reluctant to adding it to the standard Zend_Registry, because it may confuse some users.

It's a great candidate for a subclass, to demonstrate the usefulness of extending the registry component. I'm going to mark this issue as postponed for now, and we'll revisit it after ZF 1.0.

Reformat description a bit.

This is a really cool idea, but it's more exotic than what we want to include in the Framework.

I think this is a very useful feature.

  1. it makes apps scale better.
  2. it saves money on expensive resources like Oracle connection.

@allan liu: Are you aware that Zend_Db adapters already make lazy connections?

You can instantiate an adapter object inexpensively, because it doesn't connect to the RDBMS until you prepare the first query.

This behavior is documented.

Sorry I was not aware coz I am quite new in using ZF, and thanks for let me know. So Item 2 does not make sense.

Btw, Assuming I have 100 classes in Zend Registry, when ZF is setting up the registry, will ZF load all those php files?

"will ZF load all those php files?"

Short answer is yes. You store object instances into the registry, not classes.

Understand, thanks for let me know.

I'll give this idea a try as I have been thinking what to do with all my data mapper objects, which I'm instantiating here and there...