Deleting indexes from Zend_Registry and why you shouldn’t do it !

October 14, 2010

Uncategorized

p<. Zend_Registry is based on a singleton that insures that only one Zend_Registry instance is used to save global data, so that you can rely on setting and retrieving initialized values throughout your application. It is the living implementation of the "Registry design pattern(Registry design pattern explained by Martin Fowler)":http://martinfowler.com/eaaCatalog/registry.html in Zend Framework. The Zend_Registry class provides methods for adding a value to the global storage (_set_), checking if an index is set (_isRegistered_) and retrieving a previously set index (_get_). But what if you want to replace a value from the global storage?

p<. Zend_Registry provides no method to delete an existing index and trying to set an existing index will result in an Exception being thrown. Surely enough, you can use the _unsetInstance() method to delete all the existing data and repopulate, but that is most likely to do more harm than good.

p<. The solution is very simple and it involves using the SPL ArrayObject interface methods that are implemented by Zend_Registry

pre(brush: php). Zend_Registry::getInstance()->offsetUnset(‘index’);

p<. There is a reason for Zend_Registry not providing this feature. The Zend_Registry component provides a global registry to the Zend Framework, much like the $_GLOBALS array in pure PHP. The problem is that when changing values in the global registry, other parts of your application might be affected. For example if you store a cache object into the Zend_Registry and then instantiate some random class that replaces it with another value or object, you might later have a problem in another part of your application that expects the original cache reference in the Registry.

p<. In conclusion, the Zend_Registry (much like the $_GLOBALS array in PHP) is a handy and quick way to store and retrieve values and objects. That being said it enables you to develop all sorts of bad coding practices and to produce code bloat. Also it makes writing effective unit tests a pain.

p<. My advice to you is: *Don’t be lazy!*; find a way to implement “dependency injection(Read about Dependency Injection on Wikipedia)”:http://en.wikipedia.org/wiki/Dependency_injection in your classes and only pass on objects and data you actually need!

4 Responses to “Deleting indexes from Zend_Registry and why you shouldn’t do it !”

  1. mihaibojin Says:

    Now I realize I’m imagining things! I do not know why I had the impression that you couldn’t update an already set index in a Zend_Registry object. I searched for this in older ZF versions but can’t find it, so it means I invented it!
    So chelmertz I owe you an apology, you were right in your comments!

    I find this behaviour strange, as it means any part of the application can override a value in the Zend_Registry, which means you cannot actually trust the Registry.
    This further strengthens my point that a global registry is to be avoided in favor to dependency injection (this is not my original idea, I’ve read about this on tens of blogs and probably half of the web already agrees with me :)) )

  2. mihaibojin Says:

    What I’ve realized at this point is that ArrayObject is actually a class not an interface (which seems so obvious now because of it’s name!).
    When you are using the Zend_Registry instance as an object with public variables, it is in fact using the offsetSet() and offsetGet() methods from the ArrayObject class which Zend_Registry extends.
    *However, I think that this is a side effect and not a desired feature.*

    If in your example you would be using $r->get() and $r->set(), you would see that the second time you try to instantiate the same index, it would result in an exception as previously stated.

  3. chelmertz Says:

    Forgot to add something. You write "Zend_Registry provides no method to delete an existing index and trying to set an existing index will result in an Exception being thrown." which is incorrect. Try my example or the following code which works the way I describe it in 1.10.7:

    $r = Zend_Registry::getInstance();
    $r->bla = ‘blue’;
    print $r->bla.PHP_EOL;

    // changing the registry should not work, if it would, it’s as bad as globals
    $r->bla = ‘yellow’;
    print $r->bla;

  4. chelmertz Says:

    Deleting indice isn’t as bad as updating them:

    $r = Zend_Registry::getInstance();
    $player1 = new Player(1);
    $r->player = $player1;
    // allright, bootstrapped

    $player2 = new Player(2);
    // i just wanna use another player right here
    $r->player = $player2;

    Now typechecking for Player won’t even be able to tell the difference of that index’ contents.

    Zend_Registry is almost as bad as globals except that it isn’t overwritten by the same syntax as a global variable is ($blue in global scope) + you can actually typecheck for a method like this: myMethod(Zend_Registry $options) but that syntax is comprimised because of Zend_Config or just plain arrays really.

    It’s ZF’s own global scope, and it’s a really ugly solution.