Step-by-Step Pack

Zend Framework Registry Step by Step Tutorial

Use Zend_Registry to share objects across your application without globals. Learn when to use the registry, how to store config and database objects, and common anti-patterns to avoid.

Zend Framework registry pattern

What Is Zend_Registry?

Zend_Registry is a global object store. It lets you save objects (config, database adapters, loggers, or anything else) during bootstrap and retrieve them anywhere in your application. Think of it as a clean replacement for PHP global variables.

The registry is a static class with a simple API:

1
2
3
4
5
6
7
8
9
10
// Store
Zend_Registry::set('config', $configObject);

// Retrieve
$config = Zend_Registry::get('config');

// Check existence
if (Zend_Registry::isRegistered('config')) {
// ...
}

That is the entire interface. Three methods cover every use case.

Why Not Just Use Globals?

PHP global variables work, but they create invisible dependencies. Any file can overwrite a global at any time. There is no type checking, no namespace protection, and no way to know which globals a function depends on without reading every line.

Zend_Registry solves the visibility problem. You set values in the bootstrap, and the rest of your code reads from a known container. It is still global state, but it is managed and explicit.

Pack Overview

This pack connects registry usage to the config, database, and basic framework tutorials. You will see how the registry fits into the bootstrap process and how it simplifies sharing the config object and database adapter across controllers and models.

Walkthrough

Step 1 - Store Config in the Registry

After loading your configuration file in the bootstrap:

1
2
3
4
5
$config = new Zend_Config_Xml(
APPLICATION_PATH . '/configs/application.xml',
APPLICATION_ENV
);
Zend_Registry::set('config', $config);

Now any controller, model, or helper can retrieve the config without needing it passed through constructors.

Step 2 - Store the Database Adapter

If you create a Zend_Db adapter manually (rather than through Zend_Application resources), store it in the registry:

1
2
$db = Zend_Db::factory($config->database);
Zend_Registry::set('db', $db);

In a model:

1
2
$db = Zend_Registry::get('db');
$rows = $db->fetchAll('SELECT * FROM products WHERE active = 1');

This is cleaner than using Zend_Db_Table::getDefaultAdapter() in some situations, especially when you have multiple database connections.

Step 3 - Access Registry Values in Controllers

A controller action might need both config and database access:

1
2
3
4
5
6
7
8
9
10
11
12
public function listAction()
{
$config = Zend_Registry::get('config');
$perPage = $config->pagination->perPage;

$db = Zend_Registry::get('db');
$select = $db->select()
->from('products')
->limit($perPage);

$this->view->products = $db->fetchAll($select);
}

The registry keeps the controller concise. No constructor injection, no service locator class - just direct access to the objects you stored during bootstrap.

Step 4 - Use the Registry for Custom Objects

The registry is not limited to framework objects. Store anything:

1
2
Zend_Registry::set('mailer', new My_Mailer($config->mail));
Zend_Registry::set('logger', new Zend_Log($writer));

Retrieve them wherever you need. This is especially useful for objects that are expensive to create and should only be instantiated once.

When to Use the Registry

Good use cases:

  • Config objects loaded once during bootstrap
  • Database adapters that every model needs
  • Logger instances shared across the application
  • Application-wide settings like locale or timezone

Poor use cases:

  • Request-specific data (use the request object instead)
  • User session data (use Zend_Auth or Zend_Session)
  • Temporary variables (use local scope)

Common Pitfalls

Overusing the registry. If you store 20 objects in the registry, you have recreated the global variable problem with a fancier API. Keep it to shared infrastructure objects.

Getting a key that does not exist. Zend_Registry::get('missing') throws a Zend_Exception. Always check with isRegistered() first, or wrap the call in a try-catch.

Mutating registry objects. If you store a Zend_Config object and another part of the code modifies it, every consumer sees the changed values. Use read-only config objects to prevent surprises.

Using the registry instead of dependency injection. The registry is convenient but it hides dependencies. If you are writing reusable components or testable code, constructor injection is better. Use the registry for application-level wiring, not inside library code.

FAQ

Is Zend_Registry a singleton?
It uses static methods, so it behaves like a singleton. There is one global registry per request. You can also create instances with new Zend_Registry() if you need isolated containers, but this is uncommon.

Can I replace the registry with dependency injection?
Yes, and modern frameworks do exactly that. Zend Framework 2 and Laminas use a service manager (dependency injection container) instead of a registry. If you are migrating, this is a natural refactoring step.

What happens if two modules store the same key?
The second set() call overwrites the first silently. Use prefixed keys like module_users.config to avoid collisions, or document your key names clearly.

Does the registry persist across requests?
No. It lives in memory for the duration of a single PHP request. On the next request, bootstrap runs again and repopulates it. For persistent data, use sessions, cache, or the database.

How do I unit test code that uses the registry?
Set up the registry in your test setUp() method with mock objects. After the test, clear it in tearDown() using Zend_Registry::_unsetInstance(). This ensures tests do not leak state.

Articles in This Pack

  1. 1 Zend Framework Basic Tutorial
  2. 2 Zend Framework Config - Using XML File Configuration
  3. 3 Zend Framework Database - Creating Input Form
  4. 4 Zend Framework Intro - Folder Structure

Pack Checklist

  • A working Zend Framework project
  • Understanding of PHP object basics
  • Config and database components already set up
  • Familiarity with the bootstrap process