контейнеры — Внедрение параметров в конструктор с помощью PHP-DI

Я изо всех сил пытаюсь заставить внедрение зависимости работать так, как я ожидаю —

Я пытаюсь внедрить класс Api, который должен знать, к какому серверу подключаться конкретному пользователю. Это означает, что переопределение свойств конструктора в файле конфигурации бесполезно, поскольку каждому пользователю может потребоваться подключиться к другому серверу.

class MyController {
private $api;

public function __construct(Api $api) {
$this->api = $api;
}
}

class Api {
private $userServerIp;

public function __construct($serverip) {
$this->userServerIp = $serverip;
}
}

Как я могу ввести этот класс с правильными параметрами? Можно ли как-то переопределить определение? Есть ли какой-нибудь способ получить класс, вызвав контейнер с параметрами?

Чтобы (надеюсь) уточнить — я пытаюсь вызвать контейнер для создания экземпляра объекта, передавая ему параметры, которые в противном случае были бы в определении.

1

Решение

Поскольку IP зависит от пользователя, у вас, вероятно, есть некоторая логика, которая выполняет отображение user => serverIP. Это может быть чтение из базы данных или простой шард на основе идентификатора, или что-то еще. С этой логикой вы можете построить ApiFactory сервис, который создает Api для конкретного пользователя:

class ApiFactory {

private function getIp(User $user) {
// simple sharding between 2 servers based on user id
// in a real app this logic is probably more complex - so you will extract it into a separate class

$ips = ['api1.example.com', 'api2.example.com'];
$i = $user->id % 2;
return $ips[$i];
}

public function createForUser(User $user) {
return new Api($this->getIp($user);
}
}

Теперь вместо инъекций Api в ваш контроллер вы можете ввести ApiFactory (при условии, что ваш контроллер знает пользователя, для которого ему нужен экземпляр Api)

class MyController {
private $apiFactory;

public function __construct(ApiFactory $apiFactory) {
$this->apiFactory = $apiFactory;
}

public function someAction() {
$currentUser = ... // somehow get the user - might be provided by your framework, or might be injected as well
$api = $this->apiFactory->createForUser($currentUser);
$api->makeSomeCall();
}
}
1

Другие решения

Я не уверен, что полностью понимаю ваш вопрос, но вы можете настроить свой Api класс как это:

return [
'Foo' => function () {
return new Api('127.0.0.1');
},
];

Посмотрите на документацию для большего количества примеров или деталей: http://php-di.org/doc/php-definitions.html


Редактировать:

return [
'foo1' => function () {
return new Api('127.0.0.1');
},
'foo2' => function () {
return new Api('127.0.0.2');
},
];
-1

По вопросам рекламы [email protected]