1

Why should I use Zend_Registry instead of the Singleton pattern?

My coworker and me recently had a discussion about this. His point was that we should use Zend_Registry for all consistent objects, but I wanted to use the singleton pattern, since Zend_Registry just does the same, but wrapped.

I have a problem with code like this:

$list = Zend_Registry::get('database')->getList($sql);

Since theres a chance that database isn't in Zend_Registry. In cases of lazy loading, I would have to make my own registry with information about specific objects in my system. Like if the database takes specific parameters on loadtime, then it would have to know this.

I would instead use getInstance and then all the code would reside in the same object. Does that make sense?

Simon Paarlberg
  • 277
  • 2
  • 10
  • You have quite a few opinions about it here: http://stackoverflow.com/questions/1967363/registry-or-singleton and here: http://stackoverflow.com/questions/2101943/registry-or-singleton-pattern-in-php – dinopmi Sep 12 '11 at 13:41
  • http://www.phppatterns.com/docs/design/the_registry – SMka Sep 12 '11 at 13:48
  • I have a small mvc my self. I started using the singleton aproach at first and it was okay, however after time, while the code was getting more optimised it was obvious for me that the registry aproach could do what a singletin could do and a few things more. Unfortunately it's been a few month since then and do not remember the exact benefits over the singleton. – Melsi Sep 12 '11 at 16:15

2 Answers2

2

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.

David Weinraub
  • 14,144
  • 4
  • 42
  • 64
1

It does for simple blog or something. Otherwise you're stuck with only one DB instance. And that's NOT what you want in the long run. You may want to connect to other server (to log errors to central db, to import products from someone, ...) or connect as different user (for security reasons - you don't want your API to have access to admin_users table, but you still need to connect to it to check if user is valid in the first place).

You can do one-purpose registers (My_Db_Admin, My_Db_ReadOnly, ...) but that does not make much sense to me. Using registry you're not stuck with one instance. You can create one outside registry and work with it for a while and then trash it ;)

Tomáš Fejfar
  • 11,129
  • 8
  • 54
  • 82