According to Marco's Pivetta thoughts with this, this old question and my answer to an other question
I was interrogating myself about the better way to use our Services in Zend Framework 2 application.
Actually we can use the ServiceLocatorAwareInterface
combined with ServiceLocatorAwareTrait
.
With the fact In ZF3 service locator will be removed in controller It may be possible that they will also remove this interface, or advice people not using it, it make sense.
The only way I see how our Services may be constructed is :
Don't use ServiceLocator in your Services, use DependancyInjection.
The problem is :
Some project are just so big that you have either :
- 15 services's class for one workflow.
- A service's class with 15 Dependancies.
- Pick your nightmare...
Some example for what you may need in a service :
- Get back the formManager (you can't call it in the controller)
- You may need to get your ViewRenderer to render template before returning an HTML string to the view through AJAX, and JSON response;
- You may need to get back the translator or every service you want provided by ZF2
- Get your entity Manager, if you have multiple database, add count here
- Get others service like MailService, ExportService, ImportService and so on...
- If you have to load specifics services depends on a client (multi-client website in BtoB... add somes services, because you can't load | call an AbstractFactory)
Maybe for some of those points, they're can be solved by a tricks that I don't know.
My Question is :
Is it a good practise to have 15 or more Dependancies for one service and give up the ServiceLocator, in controllers, but also in services ?
Edit from comments
For illustrate my point, I paste one of my constructor :
public function __construct(
ToolboxService $toolboxService,
EntityService $entityService,
UserService $userService,
ItemService $itemService,
CriteriaService $criteriaService,
Import $import,
Export $export,
PhpRenderer $renderer
) {
$this->toolboxService = $toolboxService;
$this->entityService = $entityService;
$this->userService = $userService;
$this->emOld = $this->toolboxService->getEmOld();
$this->emNew = $this->toolboxService->getEmNew();
$this->serviceLocator = $this->toolboxService->getServiceLocator();
$this->itemService = $itemService;
$this->criteriaService = $criteriaService;
$this->import = $import;
$this->export = $export;
$this->renderer = $renderer;
$this->formManager = $this->toolboxService->getFormManager();
}
As you can see, ToolboxService is an object with multiple dependancies itself. This Service is in my Application folder, and almost everywhere. I have 2 entity Managers (connection to 2 databases, but maybe soon, i will need a third one...)
You can see that I use the serviceLocator throught a dependancy, so this service doesn't implements ServiceLocatorAwareInterface
. If I'm not using it, i'm literraly screwed for my AbstractFactory call with
// Distribute somes orders depends on Clients
$distributionClass = $this->serviceLocator->get(ucfirst($param->type));
if ($distributionClass instanceof DistributeInterface) {
$distributionClass->distribute($orders, $key);
} else {
throw new \RuntimeException("invalid_type_provided", 1);
}