In Zend Framework 1 I had several mappers which inherited a setDbTable and getDbTable from a parent Mapper class.
Now in ZF2 a face the problem that I need the service manager in a model and I do not have a clue as how to get it:
class Mapper
{
protected $tableGateway;
protected $module = 'application';
public function setTableGateway($table)
{
if (is_string($table)) {
$class = $this->module . '\Model\DbTable\\' . ucfirst($table);
$sm = $this->getServiceLocator(); <= Fatal error: Call to undefined method Mapper::getServiceLocator()
$tableGateway = (class_exists($class)) ? $sm->get($class) : $sm->get(new TableGateway($table));
} else {
$tableGateway = $table;
}
if (!$tableGateway instanceof Zend\Db\TableGateway\AbstractTableGateway) {
throw new \Exception('Invalid table data gateway provided');
}
$this->tableGateway = $tableGateway;
return $this;
}
// more code
The line:
$sm = $this->getServiceLocator();
gives a fatal error:
Call to undefined method Application\Model\Mapper\Doc::getServiceLocator()
How would I get the service manager in my model? Or am I not doing things the ZF2 way? I know how to get the service manager in my controller and pass the tableGateway to the mapper but that seems like a lot of duplication of code to me.
Service Map agents gather information about all TCP-connected processes on the server where they're installed and details about the inbound and outbound connections for each process. From the list in the left pane, you can select machines or groups that have Service Map agents to visualize their dependencies over a specified time range.
Use the SAP BTP command line interface for SAP Service Manager to perform various operations related to your service instances. Commands Task Run the command ... Link List all service instances associ ated with the current subac count.
Using the SAP BTP cockpit or Service Manager Control (SMCTL) command-line interface, create an instance of the SAP Service Manager (technical name: service-manager) with the plan: service- operator-access. Note If you can't see the needed plan, you need to entitle your subaccount to use SAP Service Manager.
Service Map integration with the IT Service Management Connector is automatic when both solutions are enabled and configured in your Log Analytics workspace. The integration in Service Map is labeled "Service Desk." For more information, see Centrally manage ITSM work items using IT Service Management Connector.
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.
Note: As Jurian Sluiman and andy124 pointed out in their comments, never inject service manger and depend on service manager inside your domain specific model/object, which is not a good practice as this will make your domain specific object rigid and impact on portability. The solution below is more specific to the question asked
I follow the below steps to get sevicelocator(service manager) in my class, models, etc
1. create class which implement ServiceMangerAwareInterface
2. Define the entry in serviceconfig in your Module.php
like this
public function getServiceConfig(){ return array( 'factories' => array( /* Models */ 'MyModule\MyModel' => function($sm) { return new Models\MyModel($sm); }, /* Entities */ 'MyModule\MyEntity1' => function($sm) { return new Entity\MyEntity1($sm); }, 'MyModule\MyEntity2' => function($sm) { return new Entity\MyEntity2($sm); }, . . . ), ); `
$model = $this->getServiceLocator()->get('MyModule\MyModel');
'service_manager' => array( 'factories' => array( 'MyModel' => 'MyModule\Models\MyModel', 'MyEntity' => 'MyModule\Entity\MyEntity', ), ),4. Access your model or class with service manager like below (ex. under controller)
$model = $this->getServiceLocator()->get('MyModel');
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With