zf2: how to get service manager in mapper-Collection of common programming errors
First of all, I think you mean that you want to access the service manager from a mapper class and not a model. I would refrain from doing the latter. Please see my comment to Raj’s answer for more details.
Secondly, there are many ways to go about this. In this answer, I will give you an example of one approach and merely mention another.
Looking at the service manager’s documentation (scroll a bit down), it states that a default initializer is added as default. This initializer checks to see if an object that is being retrieved from the service manager implements Zend\ServiceManager\ServiceLocatorAwareInterface
. If it does, the service manager is injected into the object. Thus, this can happen automatically if you simply implement the interface in your mapper classes. You could use an abstract base class to avoid rewriting this for every mapper class. Perhaps something like the below.
Base mapper class:
namespace User\Mapper;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class AbstractMapper implements ServiceLocatorAwareInterface {
protected $service_manager;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->service_manager = $serviceLocator;
}
public function getServiceLocator()
{
return $this->service_manager;
}
}
Mapper class:
namespace User\Mapper;
use User\Mapper\AbstractMapper;
class UserMapper extends AbstractMapper {
public function doSomething() {
$sm = $this->getServiceLocator();
$sm->get('something');
}
}
Since the service manager is injected when the initializer is run, the mapper should be retrieved from the service manager. If you do not want/have to inject anything into your mapper class, then an invokable can suffice. They can be added under the invokables
key, which is nested under the service_manager
key in module_name/config/module.config.php
. Or, it can be configured in the module class’ getServiceConfig
method. However, your mapper classes will most likely have some dependencies now or in the future, so you will probably want to use a factory instead. This way, you could for instance have the service manager inject a table gateway into the mapper classes.
// Remember to include the appropriate namespaces
return array(
'factories' => array(
'User\Mapper\UserMapper' => function($service_manager) {
$table_gateway = $service_manager->get('User\Model\DbTable\UserGateway');
return new UserMapper($table_gateway);
},
),
);
The above can be added in a getServiceConfig
method within the module’s Module.php
file – or add the factories
key within the service_manager
key in module_name/config/module.config.php
. You will still have to add a factory that creates the database gateway; the above is just an example.
This is how I would go about it. Of course one could simply have a getter and setter method for the service manager in the mapper class and access these from the controller (the controller has a getServiceLocator
method) and inject it like that. I would not go with that approach myself, though.
Originally posted 2013-11-10 00:11:20.