在Controller类的构造函数中获取ServiceLocator

I am building a module in . I want to access ServiceLocator in constructor of Controller class.

public function __construct() {
    var_dump($this->getServiceLocator()->get('Config'));
}

But it gives following error.

Call to a member function get() on a non-object

When I tried to get this in Action, It works perfect -

public function inAction() {
    $sm = $this->getServiceLocator();
    $config = $sm->get('Config');
}

What is the correct way to get ServiceLocator in constructor?

At the time of the construction of a class, the dependency of the ServiceLocator is not yet injected. This happens after that through initializers.

The workflow is like that:

- controller called "My\Controller\FooController"
- resolve string to classname
- $ctrl = new FooController(); // This is where __construct() is called
if $ctrl instanceof AbstractActionController
    $ctrl->setServiceLocator($serviceLocator);
endif
- return $ctrl;

The easiest workaround is to write yourself a lazy getter function inside your controller:

protected $config;

public function getConfig() {
    if (null === $this->config) {
        $this->config = $this->getServiceLocator()->get('config');
    }
    return $this->config;
}

This approach will work and you'll be happy. However you should know that this isn't actually best practice, since you call a dependency from another dependency. A better way would be to actually inject the config into your controller.

public function __construct(array $config) {
    $this->config = $config;
}

And the instead of an invokable you write a factory. This is done at best in the getControllerConfig() function of your Module-Class

public function getControllerConfig() {
    return array(
        'factories' => array(
            'My\Controller\FooController' => function($cpm) {
                $sl = $cpm->getServiceLocator();
                return new FooController(
                    $sl->get('config')
                );
            }
        )
    );
}

And then the config will be injected into your controller and it will also be available inside your __construct() in case you wanna cut out specific parts of the whole config.