Setup

Below I will demonstrate how to use an excellent Dependency Injection component from Symfony 2, without using the whole Symfony framework. I will also use ClassLoader from Symfony and just for the sake of the demo I will integrate it with Zend Framework. The code requires PHP 5.3 (mostly for namespaces support).
Create a directory for your project. Inside create “lib” directory. Inside lib, create directory structure: Symfony/Component. Put ClassLoader code inside Component – the easiest thing to do is to clone if from Symfony github:

cd lib/Symfony/Component
git clone https://github.com/symfony/ClassLoader.git

The same goes for DependencyInjection component:

cd lib/Symfony/Component
git clone https://github.com/symfony/DependencyInjection.git

Finally download Zend Framework and put the contents of Zend directory into lib/Zend (so for instance Log.php file will be available in lib/Zend/Log.php).
The actual source code will go into “src” directory, which is a sibling directory of “lib”.

Configuring the ClassLoader

DependencyInjection uses namespaces for managing classes, so it needs to be registered with registerNamespace method. Zend Framework follows PEAR naming convention for classes – registerPrefix will do the work for us. Finally, I will register our own code that will be stored in src directory. I will use namespaces as well. Create a new file (let’s call it main.php) in the top-level directory:

require_once('lib/Symfony/Component/ClassLoader/UniversalClassLoader.php');
 
$loader = new Symfony\Component\ClassLoader\UniversalClassLoader();
$loader->registerNamespace('Zabuchy',__DIR__.'/src');
$loader->registerNamespace('Symfony',__DIR__.'/lib');
$loader->registerPrefix('Zend',__DIR__.'/lib');
$loader->register();
 
set_include_path(get_include_path().PATH_SEPARATOR.__DIR__.'/lib');

ClassLoader should now work just fine but we still need set_include_path so require functions inside Zend code will work correctly.

Dependency Injection container

Create a sample class that we’ll use for testing. I will call it Test and put it into Zabuchy\Techblog, which means it should be located at src/Zabuchy/Techblog/Test.php:

namespace Zabuchy\Techblog;
 
class Test
{
    private $logger;
 
    public function __construct($logger) {
      $this->logger = $logger;
    }
 
    public function run() {
     $this->logger->info("Running...");
    }
}

$logger should be injected using container – here is where we will use Zend_Log class. This one in turn requires a Writer, so we will create it as well. The rest of main.php will look like this:

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
 
$sc = new ContainerBuilder();
 
$sc->register('log.writer','Zend_Log_Writer_Stream')
    ->addArgument('php://output');
$sc->register('logger', 'Zend_Log')
    ->addArgument(new Reference('log.writer'));
$sc->register('test','Zabuchy\Techblog\Test')
    ->addArgument(new Reference('logger'));
 
$sc->get('test')->run();

Running the code should give an output like below:

% php main.php 
2011-06-09T15:17:22+01:00 INFO (6): Running...

Complete code

For reader’s convenience I’m attaching a full source code – including a copy of Zend library and Symfony 2 components.