Even though you phrased your question as an either/or, might I suggest a third alternative?
I try to avoid both singletons and Zend_Registry
wherever possible, since they function, in effect, as globals. When a segment of code can reach into the global ether - via a call to a singleton or a global registry - to get something it needs, it creates a hidden - or at least, a non-explicit - dependency that makes things harder to debug and unit-test.
In contrast, I try to follow dependency injection advice, paraphrased as: "Give a component what it needs. Don't make it find what it needs."
I find that for most entities for which I might feel I need a registry/singleton - db connections, loggers, etc - I can create them at Bootstrap
, store them in the Bootstrap
registry and inject them into my controllers, usually during init()
using $this->getInvokeArg('bootstrap')->getResource('myResource')
. Only controllers reach back into the Bootstrap
. Then, any models or services that need these dependencies get them passed-in explicitly by the controller, either via constructor or by setter injection.
A hybrid approach to which I do sometimes fall back is to design my service/model classes with getters/setters for these dependencies - getDbAdapter()
and setDbAdapter()
; getLogger()
and setLogger()
, etc. The getter lazy-loads from the global registry - whether some singleton or by Zend_Registry, throwing exceptions when they are not where I expect them to be. In that sense, it is similar to what you are suggesting. It does violate the purist dependency injection philosophy. But at least the presence of the getter/setter methods explicitly demonstrates that there is a dependency and allows me to mock it out or to provide non-default implementations.