Accessing ServiceManager Services in Controller Plugins

Do you need access to a service from the ServiceManager in a custom Controller Plugin you’re creating? Today’s tutorial shows you just how to do it, in a testable and documentable way.


Do you need access to a service from the ServiceManager in a custom Controller Plugin you’re creating? Today’s tutorial shows you just how to do it, in a testable and documentable way.

I’ve seen some questions on Google+ and StackOverflow of late, regarding how to get access to the Zend Framework 2 database adapter, along with other ServiceManager-defined services, in a custom controller plugin.

This type of setup can come in handy for a number of situations. You may want to access services such as caching, logging or databases and want to provide a simple interface for doing so.

People seem really interested in how to do it, but how to get access to services from the ServiceManager doesn’t seem to be as clear as it could be. Gladly, there’s not much involved in actually doing it.

I’ll assume that you’re creating the plugin for an existing module. If you’re writing a stand-alone controller plugin the steps are a little different and aren’t covered in this tutorial.

To complete today’s tutorial, you only need to do 3 things:

  • Create 2 classes
  • Add a function in Module.php

The Plugin Factory

I’m a big believer in using factories (and abstract factories) in Zend Framework 2, mainly because they make constructor injection almost a breeze. So the first thing we need to do is to create a new class, called MyPluginFactory under src/Application/Mvc/Controller/Plugin/Factory.

I’m using this directory structure as it follows along with the existing Zend Framework 2 structure, which keeps your class structure well organised. Now let’s work through the class’ code.

namespace Application\Mvc\Controller\Plugin\Factory;

use Application\Mvc\Controller\Plugin\MyPlugin;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\FactoryInterface;

First we need to add in the namespace and required use statements. We’ve started with the statement for the plugin class we’ll create, followed by the two core classes we’ll need, so that the class can be managed by the ServiceManager.

class MyPluginFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $pluginManager)
    {
        $serviceManager = $pluginManager->getServiceLocator();

        return new MyPlugin($serviceManager->get('Zend\Db\Adapter\Adapter'));
    }
}

We then implement the FactoryInterface, which requires that we implement the createService() function. If you want some background on this approach, check out this article on constructor injection in Zend Framework 2.

In the method, we’re able to get access to the ServiceLocator by calling getServiceLocator() on the $pluginManager argument, initialising a new object, $serviceManager.

Then we’re able to access the database adapter service by calling the get() method on $serviceManager, specifying the key of &‘Zend\Db\Adapter\Adapter’, and pass the result to the constructor of our plugin class.

Now our plugin will have the database adapter as a fixed dependency.

The Plugin Class

Now that we have the factory class setup to manage instantiation of our plugin, let’s dive in and look at the plugin class itself.

namespace Application\Mvc\Controller\Plugin;

use Zend\Mvc\Controller\Plugin\AbstractPlugin;

As always, we start of by declaring the namespace and the use statement. In this case, we only need to specify Zend\Mvc\Controller\Plugin\AbstractPlugin.

class MyPlugin extends AbstractPlugin
{
    protected $dbAdapter;

    public function __construct(\Zend\Db\Adapter\Adapter $dbAdapter)
    {
        $this->dbAdapter = $dbAdapter;
    }
}

Now let’s look at the core of the plugin. First we have a single class member variable, $dbAdapter. We then define the class constructor, specifying one, required, argument, also called $dbAdapter, which is of type \Zend\Db\Adapter\Adapter. This will be used to initialise $dbAdapter.

Quick Note: I’m not making assumptions about what you may want to do with the database adapter; just provided enough code to show you how to get access to it. If you’d like to know more, then check out Zend\Db\Adapter\Adapter in the Zend Framework 2 manual.

The Module.php Configuration

With those two classes defined, we only need to do one more thing, which is to register the plugin in the plugin configuration. So in the module’s Module.php file, if you don’t already have it defined, define a new function, getControllerPluginConfig as follows.

public function getControllerPluginConfig()
{
    return array(
        'factories' => array(
            'MyPlugin' => 'Application\Mvc\Controller\Plugin\Factory\MyPluginFactory'
        ),
    );
}

This defines a new plugin, which we’ve named the same as the core class, MyPlugin. The elements value is the namespace of the plugin factory. When the plugin is referenced, which we’ll see in a moment, the ServiceManager will use the factory to instantiate and return the plugin with the database adapter injected.

Using It In A Controller Action

To use it, in any controller action, you can call it as follows: $this->myPlugin();. Now there’s not much you can do with it, based on the code here. So, naturally, add the relevant functions and methods you need.

That’s It!

And that’s how to create a custom controller plugin which accesses a service defined in the ServiceManager. I’d love to hear your thoughts on it in the comments.


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

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.


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