What Are Delegator Factories and Why You Should Use Them

What Are Delegator Factories and Why You Should Use Them

Ever wanted to dynamically expand the functionality of an object which you retrieve from your dependency injection container, based on different needs, yet without creating messy, hard to maintain configurations? Then you’re going to want to know about a powerful new technique - called Delegator Factories.


If you have not heard of Delegator Factories before, here’s a quote from Marco Pivetta (@ocramius), who initially implemented them.

They are pretty much a wrapper around a real factory: it allows us to either replace the actual service with a “delegate” or interact with an object produced by a factory before the Zend\ServiceManager returns it.

According to the official documentation, delegator factories:

Allow decoration of services created by your dependency injection container, across all dependency injection containers supported by Expressive.

To put my spin on it:

Delegator factories allow you to add dynamically functionality to existing services.

Let’s Consider a Practical Example

In the latest version of Zend Expressive (version 3.x), the ability to configure routes from a module’s ConfigProvider class was separated out from the Application object to an Application delegator factory called Zend\Expressive\Container\ApplicationConfigInjectionDelegator.php.

public function getRouteConfig() : array
{
    return [
        [
            'path'            => '/',
            'middleware'      => RenderMoviesMiddleware::class,
            'allowed_methods' => ['GET'],
        ],
    ];
}

What this means is that if you have been configuring your routes using a getRouteConfig function, such as in the above example, if you migrate from version 2 to 3, it’s no longer going to work. However, with a small code change, we can use the delegator factory to dynamically wrap the Application service, and continue using this configuration-driven approach, as before.

To enable it, as you can see in the code sample below, we’ve added a delegators element to config/autoload/dependencies.global.php, which returns an array. In that array, we’ve added Zend\Expressive\Application::class as a key, which references an array with one element, ApplicationConfigInjectionDelegator.

'delegators' => [
    Zend\Expressive\Application::class => [
        Zend\Expressive\Container\ApplicationConfigInjectionDelegator::class,
    ]
],

What will happen is when the DI container requests the Application service, it will have the functionality from ApplicationConfigInjectionDelegator dynamically added to it, specifically the injectRoutesFromConfig method, which is required to, as the name implies, use our ConfigProvider class’ getRouteConfig method to build up the application’s routing table.

As a result:

  • We don’t need to extend the Application object and define a new service, resulting in extra maintenance overhead for use, for the lifetime of the project.
  • We don’t need to create a one-off configuration that may get overlooked in the future, leading to hard-to-find bugs.

That’s a Wrap

The delegator factory might seem like an advanced topic, and perhaps at a development level, it is. However, at a usage level, it’s quite straight-forward and well worth using for the advantages that it provides.

If you would like help getting started, with Zend Expressive, check out the Zend Expressive Essentials book as well as the course I created from PluralSight. There are loads more resources, but I recommend these two as excellent places to start.

CC Image Courtesy of Grodenaue on Flickr


You might also be interested in these tutorials too...

Tue, Aug 9, 2016

The 3-Step Guide to Downloading Files in Zend Expressive

A common requirement of web-based applications is to upload and download files. But, out of the box, there’s no simple way to download them in Zend Expressive. This tutorial shows you how - step-by-step.

Why Is My Website So Slow?!
Fri, Sep 27, 2019

Why Is My Website So Slow?!

Is your website (or web-based application) not performing like you expect it should? Not sure why or what to do about it? Then come learn about some key things you can do to have your website perform properly.

Tue, Jul 25, 2017

How to Create a Zend Expressive Module

Ever thought of creating a Zend Expressive module, one that either scratches an itch or allows you to use a set of related functionality across multiple Zend Expressive projects? I created one recently and share how I did it with you in this three-part series.


Want more tutorials like this?

If so, enter your email address in the field below and click subscribe.

You can unsubscribe at any time by clicking the link in the footer of the emails you'll receive. Here's my privacy policy, if you'd like to know more. I use Mailchimp to send emails. You can learn more about their privacy practices here.

Join the discussion

comments powered by Disqus