2016-03-26 5 views
1

Я изо всех сил, чтобы получить зависимость инъекций работать так, как я ожидал -инъекционные параметров в конструктор с PHP-DI

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

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 зависит от u ser у вас, вероятно, есть часть логики, которая делает сопоставление user => serverIP. Это может быть чтение из db или простого id-based sharding или что-то еще. С такой логикой можно построить 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'); 
    }, 
]; 
+0

Привет, - да так в этом определении, все объекты Api будет иметь IP-адрес 127.0.0.1 «» - как я могу назвать контейнер так конкретизирует Апи с другим IP? – PointToPoint

+0

@PointToPoint см. В редакции. Также прочитайте документацию, попробуйте что-нибудь и объясните, что вы пробовали, лучше понять, где вы заблокированы. –