Make Module Configs Cacheable with the ZF2 Factory Interface

For the longest time, I’ve been using closures in my Zend Framework 2 Modules Module class. I know they’re not always the best approach, but they’re not necessarily wrong either.

But after reviewing Gary Hockin’s recent talk at PHP Conference UK, I was reminded that outside of APC and OPCache, closures aren’t cacheable.


For the longest time, I’ve been using closures in my Zend Framework 2 Modules Module class. I know they’re not always the best approach, but they’re not necessarily wrong either.

But after reviewing Gary Hockin’s recent talk at PHP Conference UK, I was reminded that outside of APC and OPCache, closures aren’t cacheable.

Depending on your application, this may not be a problem. But as most projects, invariably, grow over time, it’s likely they’ll inevitably become a performance bottleneck.

Gladly, he reminded me that there are alternative approaches which do allow for caching with Memcached, Redis and so on; specifically - if your configuration is based on a class which implements Zend\ServiceManager\FactoryInterface.

So in today’s tutorial, I’m going to show you a simple example of how to migrate from closures using this approach.

Standard Closure Approach

Ok, firstly here’s what a sample configuration in an app I’m making looks like:

class Module
{
    public function getServiceConfig()
    {
	return array(
	    'factories' => array(
                'Form\Feed\DeleteForm' => function ($sm) {
                    $form = new DeleteFeedRecordForm();
                    $form->setValidationGroup(
			array('feedId')
		    );
		    $form->setInputFilter(
			new DeleteFeedRecordInputFilter()
		    );
	            return $form;
            	},
	    )
    	);
    }
}

You can see that I’ve setup a service manager service entry, Form\Feed\DeleteForm, by using a simple closure, instantiating the form, specifying a validation group and input filter, then returning the instantiated form.

For the purposes of today’s tutorial, this will work just nicely. Let’s see how we could migrate it.

Using The Factory Interface

To implement the FactoryInterface approach, we’ll need to create a class which implements Zend\ServiceManager\FactoryInterface. Below is my class. Have a look, then let’s go over it.

<?php
namespace BabyMonitor\ServiceManager\Form\Feed;

use Zend\ServiceManager\FactoryInterface,
    Zend\ServiceManager\ServiceLocatorInterface,
    BabyMonitor\Form\DeleteFeedRecordForm as DeleteForm,
    BabyMonitor\InputFilter\DeleteFeedRecordInputFilter as DeleteFilter;

class DeleteFormFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
    	$form = new DeleteForm();
        $form->setValidationGroup(array('feedId'))
             ->setInputFilter(new DeleteFilter());
        return $form;
    }
}

As it’s configuring a service for the ServiceManager, providing a Form, managing deletion of feeds, BabyMonitor\ServiceManager\Form\Feed\DeleteFormFactory, the class namespace is semi-intuitive.

The factory interface only defines one required function, createService. I’ve included the use statements for the required classes and largely copied the code, verbatim, from the closure. Nice and simple.

Note: I've aliased the classes only for the purposes of readability and formatting. No real requirement otherwise.

Updating Module.php

With the class defined, I can now update getServiceConfig() by replacing our existing configuration with the one below:

'Form\Feed\DeleteForm' => 'BabyMonitor\ServiceManager\Form\Feed\DeleteFormFactory',

That’s it! Just one class (per/closure), and update the Module configuration. Assuming this was the only only configuration needing migration, we could then enable caching, as Akrabat explains.

Winding Up

Admittedly these were trivial examples, and depending on your configurations, you may need to go to a bit of effort to migrate your closures. But I hope you see that the migration’s quite straight-forward to do.


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

Wed, Jan 2, 2013

Zend Framework 2 Modules - The Application's Heart

Zend Framework 2 Modules - The Application's Heart

If I have seen further it is by standing on the shoulders of giants.

It’s a really exciting time at the moment with Zend Framework 2 gaining so much traction, after being stable for some time now.

Though I and countless others really enjoyed the 1.x series, it did leave some things to be desired - to be fair.

But the more I explore of the 2.x series, the more I honestly can say that I’m very impressed with it. It may not be as fast as the previous series, but with respect to development, there’s so much going for it it’s worth shouting about.

So it really is rewarding and exciting to begin covering all that it has to offer us. In part one of this series, I looked at a central concept of the revised framework - Dependency Injection.

Tue, Apr 15, 2014

Howto Use Constructor Injection In ZF2

Is it right to use setter injection? Or is it evil, to be avoided at all costs, for the explicitness of constructor injection? In today’s post, we explore that and how to implement constructor injection in ZF2 controller classes.

Thu, Apr 3, 2014

HowTo Use Child and Segment Routes to Build Simple Routing Tables

Routing is one of the key requirements in modern applications, especially in Zend Framework 2; but they shouldn’t be overly-complicated. Today, we’re going to look at how to build a routing table, simply and easily using child and segment routes.

Wed, Jan 29, 2014

Easy Setter Injection in Zend Framework 2

Want to learn how to have initialized objects with minimal code and nearly no hands-on configuration in Zend Framework 2? Come learn about setter injection.


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