The Symfony docs don't give a full example of the usage of factories in Symfony.
In my case I have many different services that generate, let's say, different fruits APIs:
Each service has it's own dependency, the dependency is some bind parameter:
services:
_defaults:
autowire: true
bind:
$guzzleClientBanana: '@eight_points_guzzle.client.banana'
$guzzleClientApple: '@eight_points_guzzle.client.apple'
...
Services are of example:
# BananaApiService.php
class BananaApiService extends DefaultEndpointService
{
protected $guzzleClientBanana;
public function __construct(GuzzleClient $guzzleClientBanana)
{
$this->guzzleClientBanana = $guzzleClientBanana;
}
public function handleRequest(ApiRequest $apiRequest)
{
...
}
}
Currently I am not using the factory pattern but instead passing all the services to a manager's constructor which is too dirty and against best practices:
# ApisManagerService
class ApisManagerService
{
protected $BananaApiService;
protected $AppleApiService;
protected $PearApiService;
public function __construct(BananaApiService $BananaApiService,
AppleApiService $AppleApiService,
PearApiService $PearApiService)
{
$this->BananaApiService = $BananaApiService;
//...
}
public function requestDispatcher(ShoppingList $shoppingList): void
{
foreach ($shoppingList->getItems() as $item) {
switch ($item->getName()) {
case 'banana':
$this->BananaApiService->handleRequest($item);
break;
case 'apple':
$this->AppleApiService->handleRequest($item);
break;
//...
}
}
}
}
This requestDispatcher is called via some event subscriber:
class EasyAdminSubscriber implements EventSubscriberInterface
{
public function triggerApisManagerService(GenericEvent $event): void
{
/* @var $entity shoppingList */
$entity = $event->getSubject();
if (! $entity instanceof shoppingList) {
return;
}
$this->apisManagerService->requestDispatcher($entity);
}
}
How can I make the code better using Symfony factories (or other Symfony approaches)?
I would advise to take a look at the implementation of strategy pattern for this specific case. It would be a way cleaner solution than all-services constructor injection, especially if there are cases when all services are not needed to be used - with strategy pattern you will use only the needed services (at application run-time), & handle their specific logic.