Skip to end of metadata
Go to start of metadata
You are viewing an old version of this page. View the current version. Compare with Current  |   View Page History

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

Zend Framework: Zend_Di Component Proposal

Proposed Component Name Zend_Di
Developer Notes
Proposers My E-mail Address
Revision 0.1 - 21 November 2007: Initial Proposal.
0.2 - 29 November 2007: Added a real-life example.
0.3 - 30 November 2007: API reworked.
0.4 - 12 February 2008: API reworked. (wiki revision: 59)

Table of Contents

1. Overview

Zend_Di is a dependency injector component. It minimizes coupling between groups of classes, makes unit testing much simpler, and provides an easy way to re-configure a package to use custom implementations of components. The architecture of the Zend_Di component is based on the following concepts:

  • Dependency injection is a technique that consists of passing objects via the constructor or setter methods.
  • The Container provides an easy way of re-configuring a package to use custom implementations of components.
  • Responsibility for object management is taken over by whatever container is being used to manage those objects.

Benefits of using a DI Container:

  • Easy best practice unit testing
  • Component reuse
  • Centralized configuration
  • Clean and declarative architecture
  • Maintainability and adaptability

2. References

3. Component Requirements, Constraints, and Acceptance Criteria

  • This component will use Reflection.

4. Dependencies on Other Framework Components

  • Zend_Config (optional)
  • Zend_Exception
  • Zend_Loader

5. Theory of Operation

Zend_Di provides generic factory classes that instantiate instances of classes. These instances are then configured by the container, allowing construction logic to be reused on a broader level. For example:

Once we separate configuration from use, we can easily test the Car with different Engines. It's just a matter of re-configuring the package and injecting Zend_Car_Parts_Engine_Gas instead of Zend_Car_Parts_Engine_Fuel.

6. Milestones / Tasks

  • Milestone 1: [DONE] Design interface
  • Milestone 2: [DONE] Write proposal
  • Milestone 3: [IN PROGRESS] Gather feedback and revise design as necessary
  • Milestone 4: Review by the Zend team
  • Milestone 5: Develop full implementation and unit tests
  • Milestone 6: Documentation
  • Milestone 7: Future enhancements

7. Class Index

  • Zend_Di
  • Zend_Di_Container
  • Zend_Di_Factory
  • Zend_Di_Reflection
  • Zend_Di_Parameter
  • Zend_Di_Data
  • Zend_Di_Registry
  • Zend_Di_Storage_Interface
  • Zend_Di_Storage_Object
  • Zend_Di_Storage_Exception
  • Zend_Di_Exception

8. Use Cases

Zend_Di handles injections via the constructor or setters methods. In addition, the component allows the user to map out specifications for components and their dependencies in a configuration file and generate the objects based on that specification.

The cases below assume that the following classes have been defined:

Assembling Objects Using Configuration

The configuration is typically set up in a different file. Each package can have its own configuration file: PHP, INI or XML file. The configuration file holds the components specifications and package dependencies.

You can pass an instance of Zend_Config via the constructor, or set a configuration array using the setConfigArray() method.


The two major flavors of Dependency Injection are Setter Injection (injection via setter methods) and Constructor Injection (injection via constructor arguments). Zend_Di provides support for both, and even allows you to mix the two when configuring the one object.

Constructor dependency injection

When a class is loaded, the constructor method is selected by default.


Users can map out specifications for components and their dependencies. So whenever a class is loaded, Zend_Di will inject the dependencies automatically. For example:


Setter dependency injection


Zend_Di injects dependencies using the top-down fashion, starting with the constructor and ending with the setter methods.


Users can map out specifications for a component:


Storage Containers

You can tell Zend_Di what components to manage by adding them to a container (the order of registration has no significance). Containers are stored are retrived using the Zend_Di_Registry class. The Zend_Di_Registry::getContainer() method returns an instance of Zend_Di_Storage_Interface.


You can register your own container as long as you pass an instance of Zend_Di_Container_Storage_Interface. New containers can be register using the registerContainer() method.


Assembling Objects Using Reflection

If this was to be implemented, we need to think about what to do if we have more than one object that implements the same interface. For example:


Real-life Example

Zend_Import is a component I use to import SQL, XML and CSV files into the database. I created the Zend_Di component because:

  • I needed a way to test Zend_Import with different file formats and using different protocols.
  • I wanted to minimize coupling between the components.
  • I wanted other developers to know the components Zend_Import was using by looking at the config file or API.
  • I wanted to minimize the risk of having hidden dependencies.

The CSV files are retrieved using FTP, and the XML files using HTTP. Because the script is run by a Cron job, I also added logging capabilities to Zend_Import.

The problem I faced when designing Zend_Import was the amount of dependencies the component had: Zend_Import_Protocol, Zend_Db, Zend_Log, Zend_Log_Writer and Zend_Mail (recently added, and not included in this example). So I decided to use the dependency injection pattern to solve this problem.

Zend_Di has been tested with Zend_Import in a staging server. Below is a prototype of the Zend_Import package, and a brief example of how Zend_Import takes full advantage of the DI pattern.

Zend_Import package:


Prototype of the Zend_Import_Format_Csv class:


This will output:

9. Class Skeletons

  • Zend_Di_Container
  • Zend_Di_Factory
  • Zend_Di_Parameter
  • Zend_Di_Registry
  • Zend_Di_Storage_Object


Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.