Насколько я понимаю, действительный шаблон:
Вопрос в том, что является действительным / подходящим шаблоном для
включая / внедряя эти другие взаимосвязанные услуги?
Реальный пример того, что мы сейчас очень упрощаем:
AuctionController
/**
* get vehicles for specific auction
*/
public function getVehiclesAction ()
{
$auctionService = $this->getAuctionService(); // via service locator
$auctionID = (int) $this->params('auction-id');
$auction = $auctionService->getAuctionVehicle($auctionID);
return $auction->getVehicles();
}
AuctionService
public function getAuctionVehicles($auctionID) {
$auction = $this->getAuction($auctionID);
// verify auction (active, permissions, ...)
if ($auction) {
$vehicleService = $this->getVehicleService(); // via service locator
$vehicleService->getVehicles($params); // $params = some various conditions or array of IDs
}
return false;
}
VehicleService
public function getVehicles($params) {
$cache = $this->getCache(); // via service locator
$vehicles = $cache->getItem($params);
if (!$vehicles) {
$vehicleDB = $this->getVehicleDB(); // via service locator
$vehicles = $vehicleDB->getVehicles($params);
}
return $vehicles;
}
Пример предложенного правильного шаблона
AuctionController
public function __construct(AuctionService $auctionService) {
$this->auctionService = $auctionService;
}
/**
* get vehicles for specific auction
*/
public function getVehiclesAction ()
{
$auctionID = (int) $this->params('auction-id');
$auction = $this->auctionService->getAuctionVehicle($auctionID);
return $auction->getVehicles();
}
**AuctionService**
public function getAuctionVehicles($auctionID) {
$auction = $this->getAuction($auctionID); // no problem, local function
// verify auction (active, permissions, ...)
if ($auction) {
$vehicleService = $this->getVehicleService(); // we don't have service locator
$vehicleService->getVehicles($params); // $params = some various conditions or array of IDs
}
return false;
}
VehicleService
public function getVehicles($params) {
$cache = $this->getCache(); // we don't have service locator, but cache is probably static?
$vehicles = $cache->getItem($params);
if (!$vehicles) {
$vehicleDB = $this->getVehicleDB(); // where and how do we get this service
$vehicles = $vehicleDB->getVehicles($params);
}
return $vehicles;
}
Некоторые заметки:
Если контроллеру требуется слишком много разных служб, это обычно является показателем того, что у контроллера слишком много обязанностей.
В ответ на ответ @ AlexP, этот сервис будет добавлен в ваш контроллер. В зависимости от вашей настройки, это может привести к каскаду внедрения зависимостей при создании контроллера. Это по крайней мере ограничит созданные сервисы теми, которые фактически требуются контроллером (и те, которые связаны транзитивно).
Если некоторые из этих служб требуются редко, и вы беспокоитесь о том, чтобы создавать их все при каждом запросе, новый Service Manager теперь поддерживает ленивые услуги тоже. Они все еще могут быть введены в сервис / контроллер как обычная зависимость (как указано выше), но создаются только при первом вызове.
Копируем это из примера документации:
$serviceManager = new \Zend\ServiceManager\ServiceManager([
'factories' => [
Buzzer::class => InvokableFactory::class,
],
'lazy_services' => [
// Mapping services to their class names is required
// since the ServiceManager is not a declarative DIC.
'class_map' => [
Buzzer::class => Buzzer::class,
],
],
'delegators' => [
Buzzer::class => [
LazyServiceFactory::class,
],
],
]);
При запросе сервиса он не создается сразу:
$buzzer = $serviceManager->get(Buzzer::class);
Но только когда это впервые используется:
$buzzer->buz();
Таким образом, вы можете добавить несколько зависимостей в ваш контроллер, и будут созданы только те службы, которые действительно необходимы. Конечно, это верно для любой зависимости, такой как Услуги, требуемые другими службами, и так далее.
Вы могли бы составить новый сервис, скажем VehicleAuctionService
и оба AuctionService
а также VehicleService
вводится как зависимость с использованием фабрики.
Это объектная композиция.
class VehicleAuctionService
{
private $auctionService;
private $vehicleService;
public function __construct(
AuctionService $auctionService,
VehicleService $vehicleService
){
$this->auctionService = $auctionService;
$this->vehicleService = $vehicleService;
}
public function getAuctionVehicles($auctionID)
{
$auction = $this->auctionService->getAuction($auctionID);
if ($auction) {
$params = [
'foo' => 'bar',
];
$this->vehicleService->getVehicles($params);
}
return false;
}
}