Previous Next

Generating Service Locators

In production, you want things to be as fast as possible. The Dependency Injection Container, while engineered for speed, still must do a fair bit of work resolving parameters and dependencies at runtime. What if you could speed things up and remove those lookups?

The Zend\Di\ServiceLocator\Generator component can do just that. It takes a configured DI instance, and generates a service locator class for you from it. That class will manage instances for you, as well as provide hard-coded, lazy-loading instantiation of instances.

The method getCodeGenerator() returns an instance of Zend\CodeGenerator\Php\PhpFile, from which you can then write a class file with the new Service Locator. Methods on the Generator class allow you to specify the namespace and class for the generated Service Locator.

As an example, consider the following:

use Zend\Di\ServiceLocator\Generator;

// $di is a fully configured DI instance
$generator = new Generator($di);

$generator->setNamespace('Application')
          ->setContainerClass('Context');
$file = $generator->getCodeGenerator();
$file->setFilename(__DIR__ . '/../Application/Context.php');
$file->write();

The above code will write to ../Application/Context.php, and that file will contain the class Application\Context. That file might look like the following:

getMyComposedClass();
        
            case 'struct':
            case 'My\Struct':
                return $this->getMyStruct();
        
            default:
                return parent::get($name, $params);
        }
    }

    public function getComposedClass()
    {
        if (isset($this->services['My\ComposedClass'])) {
            return $this->services['My\ComposedClass'];
        }
        
        $object = new \My\ComposedClass();
        $this->services['My\ComposedClass'] = $object;
        return $object;
    }
    public function getMyStruct()
    {
        if (isset($this->services['My\Struct'])) {
            return $this->services['My\Struct'];
        }
        
        $object = new \My\Struct();
        $this->services['My\Struct'] = $object;
        return $object;
    }

    public function getComposed()
    {
        return $this->get('My\ComposedClass');
    }

    public function getStruct()
    {
        return $this->get('My\Struct');
    }
}

To use this class, you simply consume it as you would a DI container:

$container = new Application\Context;

$struct = $container->get('struct'); // My\Struct instance

One note about this functionality in its current incarnation. Configuration is per-environment only at this time. This means that you will need to generate a container per execution environment. Our recommendation is that you do so, and then in your environment, specify the container class to use.

Previous Next