How to get dependencies into Zend Framework 2 controllers

There’s more than one way to do this, three of which are:

  • Define an interface for each dependency and define in your config the name of the concrete class that should be automatically instantiated by dependency injection.
  • Create a Factory class, implementing┬áZend\ServiceManager\FactoryInterface and reference the factory in your controller configuration.
  • Define a factory closure in Module.php

Here I’ll describe the third of these, as this is my preferred approach.

In your Module.php

1
2
3
4
5
6
7
8
9
10
11
12
public function getControllerConfig()
{
    return array(
        'factories' => array(
            'Course' => function(ControllerManager $cm) {
                return new Controller\CourseController(
                    $cm->getServiceLocator()->get('CourseService')
                );
            },
        ),
    );
}

Here, the ‘Course’ refers to the controller you define for your routes in module.config.php, e.g.

1
2
3
4
5
6
7
8
9
10
11
12
13
'delete-course' => array(
    'type'    => 'Segment',
    'options' => array(
        'route'    => '/delete[/:courseId]',
        'constraints' => array(
            'courseId' => '[0-9]+'
        ),
        'defaults' => array(
            'controller' => 'Course',
            'action'     => 'delete',
        ),
    ),
),

You should ensure that you don’t have ‘Course’ listed in module.config.php in your invokables section, e.g.

1
2
3
4
5
6
7
8
9
10
'controllers' => array(
    'invokables' => array(
        /****************************************************************************************
        DON'T DO THIS! - You should remove the reference you may already have in this section,
        otherwise, ZF2 will try to instantiate your controller without any arguments and you'll
        get an error.
        *****************************************************************************************/
        'Course' => 'Application\Controller\CourseController',
    ),
),

The ‘CourseService’, on the other hand, does need to be defined as an invokable in your module.config.php in the service_manager section, e.g.

1
2
3
4
5
6
7
8
9
10
11
12
'service_manager' => array(
    'abstract_factories' => array(
        'Zend\Cache\Service\StorageCacheAbstractServiceFactory',
        'Zend\Log\LoggerAbstractServiceFactory',
    ),
    'aliases' => array(
        'translator' => 'MvcTranslator',
    ),
    'invokables' => array(
        'CourseService' => 'Application\Service\CourseService',
    ),
),

Once this is done, the following code should assign an instance of CourseService to the member variable of the CourseController:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class CourseController extends NetsensiaActionController
{
    /**
     * @var Application\Service\CourseService
     */
    private $courseService;
 
    public function __construct(
	   CourseService $courseService
    )
    {
        $this->courseService = $courseService;
    }
}

{ 1 comment… add one }

  • Marcus Floyd January 11, 2014, 11:14 pm

    Thanks for this post. Could you give an example of the first method mentioned:

    “Define an interface for each dependency and define in your config the name of the concrete class that should be automatically instantiated by dependency injection.”

    In my case, I have a custom class in vendor… let’s call it “Namespace\My\Class”

    I’m trying to figure out how to get this class injected into all controllers, but haven’t been able to figure it out and it seems the first option in this post will work the best for me.

    Thanks for any help.

    Reply

Leave a Comment