Better Alternatives to using Zend_Registry

Code Naked

  • Homepage
  • About
  • Contact

Sep 10: Better Alternatives to using Zend_Registry

Don't get me wrong, I think the Zend_Registry component is great. There are a couple of problems that I see when using the Zend_Registry as a container for junk like database connection objects and session namespaces and pretty much every other resource that you need to be globally accessible. The first, is that there is no information about what kinds of resources are available to you when you are using the registry. In other words, there is no way to know what Zend_Registry::get('db'); is actually going to give you. Is it a Database connection resource or is it a Data Buffer? Actually, it almost makes more sense for "db" to be an acronym for data buffer ... At any rate, there is no way to enforce what you are getting. This means that your editor can't code hint for you and your API docs don't really show an object that has the responsibility of wrangling application resources. I guess that is a good summary for the first issue with Zend_Registry - it's too generic to be really useful.

The second problem with the Zend_Registry is that it is essentially a global array. At any given time an innocent developer can unwittingly blow away your database connection with his data buffer and there is nothing to stop him. We all know (or should know) that global variables are bad. They inject uncertainty into our applications and can be the cause of some of the most irritating to debug problems. So, to sum up the second issue with Zend_Registry - it suffers from the same issues that all global variables suffer.

So, how do we fix it. Simple really, we create an object that is responsible for maintaining these application services. In fact, I use two different objects to manage two different types of application resource. I use Naked_App_Environment to manage configuration and environment information and I use Naked_App_Workspace to manage my application resources such as Naked_Db connections and Zend_Logger instances. Let's take a look at these two components and see how your life as a developer can be made better...
Every application has a myriad of configuration and environment settings that affect the way it runs. Configuration options include such things as your database connection username and password or the routes that you use for translating URL paths into MVC actions. The environment includes such things as the base path of the application or whether you are being run from CLI or from an HTTP request. This information should be contained in one easy to find place. For my applications, that place is my Naked_App_Environment.

There are only a few methods in this object as most of its properties are accessed through magic getters. My __set method actually throws an exception so that although it looks like you can access the properties as if they were public, you can't actually modify them from outside of the Environment class itself. Basically it's like setting a read-only attribute in other languages such as .Net that support that feature.

The real meat of the Environment is contained in the init method shown here
This method performs the following actions:

1. Sets up the paths for the application
2. Adds the paths for models, mappers and annotations to the include path
3. Loads the common config file and sets it to be modifiable using the third parameter to the constructor
4. Loads the module specific config files and merges them this the common config
5. Sets the config to read-only, preventing further modification of the configuration.
6. Registers the autoloader
7. Sets the locale and timezone

There are a couple of other helper methods, isDevEnvironment is used to determine if we are running in development or production. Things like the debugger only run in development. isCLI is used to determine if we are running from command line or not. Even if you think that your application runs solely from HTTP requests, you should ask yourself what happens if you try to start your session in a unit test. You unit test your code right? After the Environment is all set up it's like turning on a light in a dark room, you can suddenly see what's around you and prepare to take action.

If your action is to write a note to someone you take a look at your pencil holder to see what's available to you. The holder contains pens, pencils, erasers, scissors and sharpie markers which you may need for the various tasks you do through your day, but for this task you only need the pen. Next you have to get something to write on. You look in your drawer to find letter paper, post-it notes envelopes and more. Selecting the letter paper you look for a clear place to write on - your desk seems like the logical place. Perhaps the analogy was a little drawn-out, but the point I am trying to make is that in order to get your task complete you need more than just the pencil holder, you need a workspace. In my applications that's exactly where I keep components that I need to get work done, the Naked_App_Workspace.

The workspace is also pretty simple - I hope that's a common theme you get from all of my code examples - it's basically just pairs of init and get methods. I have a common init method that calls all of the individual init methods to get everything ready. I do have lazy initialization in place as well, but that's more for unit testing scenarios than anything else. Lets take a look at the pair of methods for initializing and getting the Database connection.

So now when I type $app->workspace->getDb() I get code hints and everything! Sweet! Here is a list of the components that I have in my workspace at this point:

1. Logger - Zend_Log with two writers, stream and optionally FirePHP if in a dev environment
2. Cache - My own memcache wrapper that supports stats calls
3. Db - You know this one already
4. Auditor - Listens for signals from the UnitOfWork and writes an audit trail
5. UnitOfWork - An implementation of the Unit of Work pattern
6. Auth - Simple Zend_Auth setup
7. ACL - My own ACL junk
8. Translator - Zend_Translate instance
9. Layout - Zend_Layout instance
10. Signals - Top secret until I can post about it later.

These two classes have helped me tremendously in keeping a proper separation of concerns between the objects that I need to get work done and the objects that I am actually doing the work on.
Posted by Matthew Purdon in PHP Comments: (0) Trackbacks: (0)

Trackbacks
Trackback specific URI for this entry

No Trackbacks

Comments
Display comments as (Linear | Threaded)

No comments


Add Comment

Standard emoticons like :-) and ;-) are converted to images.
 
 

Subscribe

Archives

  • March 2010 (0)
  • February 2010 (1)
  • January 2010 (4)
  • December 2009 (6)
  • Recent...
  • Older...

Categories

  • XML Technology
  • XML Databases
  • XML MySQL
  • XML Software Development
  • XML Being a Contractor
  • XML Client Side
  • XML PHP
  • XML State of the Art


All categories

Blog Administration

Open login screen

Recommended Reading

Amazon.com: Domain-Driven Design: Tackling Complexity in the Heart of Software (0076092019565): Eric Evans: Books
Amazon.com: Refactoring: Improving the Design of Existing Code (9780201485677): Martin Fowler, Kent Beck, John Brant, William Opdyke, Don Roberts: Books
Amazon.com: The Nomadic Developer: Surviving and Thriving in the World of Technology Consulting (9780321606396): Aaron Erickson: Books
Amazon.com: Patterns of Enterprise Application Architecture (0076092019909): Martin Fowler: Books

Feedburner

Numeric Feedburner ID Required!




 

Layout by Andreas Viklund | Serendipity template by Carl