Reputation: 21286
My application is a collection of POPO's and I'm trying to wire these POPO's up using the Zend Framework 2 Service Manager.
To illustrate my problem, take the following example:
$config = array(
'services' => array(
'my.app.serviceA' => new \My\App\Services\ServiceA(),
'my.app.serviceB' => new \My\App\Services\ServiceB(),
'my.app.manager.task' => new \My\App\Manager\TaskManager(),
),
);
My TaskManager class looks something like this:
class TaskManager {
protected $serviceA;
protected $serviceB;
public function setServiceA( \My\App\Service\ServiceA $serviceA )
{
$this->serviceA = $serviceA;
}
public function setServiceB( \My\App\Service\ServiceB $serviceB )
{
$this->serviceB = $serviceB;
}
}
As you can see, the TaskManager
class has dependencies on both ServiceA
and ServiceB
. How do inject those services into my.app.manager.task
using the Service Manager configuration using the service names defined for both ServiceA
and ServiceB
?
UPDATE:
I'm beginning to believe that I shouldn't be using the ServiceManager component for my purposes at all but that I should be using the Zend DI component instead.
I get the impression that the ServiceManager is a ZF2 "framework" component whereas Zend\DI seems to be more of a generic all purpose DiC. Hence, this might be the reason of ServiceManager's tied relationship with the MVC and ModuleManager components (which also seem to be "framework" components).
Maybe someone could clarify?
Upvotes: 0
Views: 2656
Reputation: 122
for me, the best way is to create a class factory and use the factoryInterface, like this :
return array(
'service_manager' => array(
'factories' => [
'Task' => 'Application\TaskFactory',
],
'invokables' => array(
'Task'=> 'Application\Task',
'ServiceA'=> 'Application\ServiceA',
'ServiceB' => 'Application\ServiceB'
)
),
);
And a factory class :
class TaskFactory implements FactoryInterface {
/** @var ServiceLocatorInterface $serviceLocator */
var $serviceLocator;
public function createService(ServiceLocatorInterface $serviceLocator) {
$sl = $this->serviceLocator = $serviceLocator;
// you can get your registered services
$serviceA = $sl->get('ServiceA');
$serviceB = $sl->get('ServiceB');
// You can build your class using the class loader
$task = new Application\Task();
// Or the Service Locator Again
$task = $sl->get('Task');
return $task;
}
}
You can implement the factory interface on your Task class. I prefer to have control on what I'm building.
Upvotes: 0
Reputation: 530
in Controller ;
$yourService = $this->getServiceLocator()->get('your_service_alias');
in View Helper : you should send in from Module.php by constructor of viewHelper
public function getViewHelperConfig() {
return array(
'factories' => array(
'loginHelper' => function($sm) {
return new LoginHelper($sm);
}
)
}
in a calss
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
public class UseCaseBO implements ServiceLocatorAwareInterface {
protected $serviceLocator;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator) {
$this->serviceLocator = $serviceLocator;
}
public function getServiceLocator() {
return $this->serviceLocator;
}
// now instance of Service Locator is ready to use
public function someMethod() {
$table = $this->serviceLocator->get('your_service_alias');
//...
}
}
Upvotes: 0
Reputation: 530
in module.config.php The Service Manager can be configured in 7 different ways:
return array(
// instantiate the class for you when needed
'invokables' => array(
'commentController' => '\Comment\Controller\CommentController';
),
// Aliasing a name to a known service name
'aliases' => array(
'Comment\Service' => 'commentService';
),
// configure the instance of the object
'factories' => array(
'commentController' => function ($sm) {
$locator = $sm->getServiceLocator();
$controller = $locator->get('commentController');
$controller->setCommentService($locator->get('Comment\Service'));
return $controller;
}
),
// register already instantiated objects
'services' => array(
'commentController' => new \Comment\Controller\CommentController(),
),
//factory instance that can create multiple services based on the name supplied to the factory.
'abstract_factories' => array(
'SomeModule\Service\FallbackFactory',
),
// initialize the service whenever service created
'initializers' => array(
function ($instance, $sm) {
if ($instance instanceof \Comment\Controller\CommentController){
$instance->setCommentService($sm->get('Comment\Service'));
}
}
),
// indicating whether or not a service should be shared
'shared' => array(
'commentController' => false,
),
);
and in Module.php
public function getControllerConfig() {
return array(
'factories' => array(
'commentController' => function ($sm) {
$controller = new \Comment\Controller\CommentController();
$locator = $sm->getServiceLocator();
$controller->setCommentForm($locator->get('commentForm'));
$controller->setCommentService($locator->get('commentService'));
return $controller;
}
)
);
}
and simple use in controller :
$commentService = $this->serviceLocator->get('Comment\Service');
you put this in getter or in init() method ZF2's New Controller::init() :: phly, boy, phly
Upvotes: 2