Using Delegators in Zend Framework

  • Viewed 169×

  • Blog

Delegators (delegation pattern) in Zend Framework are very useful in situations when you need to add some configuration or dependency during instantiation of service class (service manager knows about that class). You will achive it with a delegator factory. The factory wraps your service and provides additional "decoration".

I'm often using delegators to set language or user identity in a model classes. For example, when model creates sql query where language is a parameter, I'm sure I have this parameter set (thanks to delegator factory) and I can just call getLanguage(). So there is no need to pass language parameter into model class from controller for example.
Let's make this use case.

Delegator factory

We will need an interface and delegator factory classes for that. I will put them into folder Service in the Application module.

└─ module
   └── Application
       ├── config
       │   ├── module.config.php
       │   └── template_map.config.php
       ├── src
       │   ├── Controller
       │   ├── Entity
       │   ├── Form
       │   ├── Model
       │   ├── Service
       │   │   ├── LanguageInterface.php
       │   │   └── LanguageDelegatorFactory.php
       │   ├── View
       │   │   └── Helper
       │   └── Module.php 
       └── view


namespace Application\Service;

interface LanguageInterface

     * @return string
    public function getLanguage();

     * @param string $language
    public function setLanguage($language);


namespace Application\Service;

use Zend\ServiceManager\Factory\DelegatorFactoryInterface;
use Interop\Container\ContainerInterface;
use Zend\Session;

class LanguageDelegatorFactory implements DelegatorFactoryInterface

    public function __invoke(ContainerInterface $container, $name, callable $callback, array $options = null)
        $serviceToWrap = $callback();

        if (! $serviceToWrap instanceof LanguageInterface) {
            return $serviceToWrap;

	// distinguishing of language
        $request = $container->get('request');
        $uri = $request->getUri();
        $path = $uri->getPath();
        $urlParts = explode('/', $path);

        if (isset($urlParts[1]) && $urlParts[1] == \Admin\Module::SESSION_CONTAINER) {
            // admin
            $sessionContainerName = \Admin\Module::SESSION_CONTAINER;
        } else {
            // front
            $sessionContainerName = \Application\Module::SESSION_CONTAINER;

        $session = new Session\Container($sessionContainerName);

        return $serviceToWrap;

Our delegator is ready to be used. Lets have another module in our application named Item, where we will select items depending on language, besides. Our model ItemContentTable implements LanguageInterface so we need to define setLanguage() and getLanguage() methods.

namespace Item\Model;

use Werc\Db\AbstractTable;
use Zend\Db\TableGateway\TableGateway;
use Application\Service\LanguageInterface;
use Zend\Db\Sql\Sql;

class ItemContentTable extends AbstractTable implements LanguageInterface
    public $primary = 'id';

    protected $tableGateway;

    protected $language;

    public function __construct(TableGateway $tableGateway)
        $this->tableGateway = $tableGateway;

    public function getLanguage()
        return $this->language;

    public function setLanguage($language)
        $this->language = $language;

     * @param int $id
     * @return ArrayObject|NULL
    public function selectOne($id)
        $adapter = $this->tableGateway->getAdapter();
        $sql = new Sql($adapter, $this->tableGateway->getTable());
        $select = $sql->select();
        $select->join('item', $this->tableGateway->getTable() . '.item_id =',
            ), 'left');
        $select->where->equalTo('item_id', $id);
        $select->where->equalTo('lang', $this->getLanguage());
        $sqlString = $sql->buildSqlString($select);

        return $this->getResultSet($sqlString)->current();

At last, in a module config we tell the service manager to "decorate" our model ItemContentTable with LanguageDelegatorFactory.


namespace Item;

return array(
    'controllers' => array(
    'service_manager' => array(
        'factories' => array(
            Model\ItemContentTable::class => Model\ItemContentTableFactory::class
        'delegators' => array(
            Model\ItemContentTable::class => array(



Similarly you can solve any cases when you need to refer some parameters to a class automatically.


There is one more way how to solve similar principle in Zend Framework, initializers. Initializers were introduced in Zend Framework 2 and I'm not sure about a bright future. They have been primarily kept for backwards compatibility and have several disadvantages also. Marco Pivetta (Ocramius) has an excellent article on initializer performance problem. So keep distance from initializers and use delegator factories rather.


  1. Delegators, Zend Framework documentation.
  2. Initializers, Zend Framework documentation.
  3. Delegator Factories in Zend Framework 2, Ocramius blog.