2

내가 제공해야하는 변수가 아닌 정적 매개 변수가있을 때 Dependency Injection 컨테이너를 사용하는 방법은 무엇입니까? 사용자 이름을 변경할 수 있으며, 실행시에 공급되는가변수 매개 변수가 필요한 클래스를 Dependency Injection 컨테이너에 배치하는 방법은 무엇입니까?

$staff = new Staff("my_great_username"); 

참고 :

$staff = $container->get(Staff::class); 

는 내가 지금 가지고있는 것은 이것이다 :

은 내가 내 코드에서 원하는 것은 이것이다 .

변수 매개 변수를 지정할 방법이 없기 때문에 DI 컨테이너에 Staff을 넣을 수 없습니다.

class StaffFactory 
{ 
    function __invoke(ContainerInterface $container): Staff 
    { 
     /* 
     * I do not seem to know how to get my username here 
     * nor if it is the place to do so here 
     */ 
     $staff = new Staff(????????); 
     return $staff; 
    } 
} 

내가 설정하는 방법 : 내 문제가

... 내가 공장 기반의 컨테이너를 사용하고

, 즉 Zend\ServiceManager\ServiceManager .This 내가 인스턴스 세부 사항을 숨기는 데 사용하는 공장 내 설정에서 컨테이너를 올리면 다음과 같습니다.

'factories' => [ 
    Staff::class => StaffFactory::class 
] 

참고 : 매개 변수가 "변수"임에도 불구하고을 원합니다.은 변경할 수 없습니다. 즉, 일단 그것이 생성되면, 그것은 그렇게 계속됩니다. 따라서 사용자 이름에 대해 특별히 setter 메소드를 만들고 싶지는 않습니다. 그렇지 않으면 클래스가 변경 가능하다는 것을 의미합니다.

무엇을 제안합니까?

+0

이 질문을 올리면 xD – Dennis

+0

내가 혼란스러워 - IOC 컨테이너를 서비스 로케이터로 사용하는 이유는 무엇입니까? 특히 구체적인 클래스를 사용하는 이유는 무엇입니까? new를 통해 이점이없는 것으로 보입니다. ' – Steve

+0

IoC를 서비스 위치 지정자로 사용하는 경우는 어디에서 볼 수 있습니까? 내가 이해할 때, 나는 $ 컨테이너를 $ 클래스에 삽입 할 때만 서비스 로케이터가된다. 원하는 클래스를 가져올 수있다.'ServiceManager'는 공장 기반의 IoC로, 부팅 스트랩의 일부로'$ container'를 사용하는 한, IoC로 남아 있습니다. 일명 Factory에'$ container'를 주입하는 것은 IoC의 용납 사례이며, 그 주입은 그 공장에 국한되어 있고 내 자신의 클래스에 유출되지 않기 때문에 서비스 위치 패턴을 피할 수 있습니다. – Dennis

답변

1

내 문제는 내 Staff 클래스의 생성자에 전달되는 변수 매개 변수가 있다는 것이 었습니다.

해결책은 생성자에 변수 매개 변수가없는 StaffCreator 클래스를 만든 다음 변수 매개 변수를 사용하는 StaffCreator::create 메서드를 작성하는 것입니다. 그런 다음 Staff이 필요한 모든 클래스에 주입하는 대신 StaffCreator을 삽입 한 다음이를 사용하여 Staff 인스턴스를 만듭니다.

신용을 가진
//Inject this wherever you need Staff 
$staffCreator = $container->get(StaffCreator::class); 

//use it: 
$staff = $this->staffCreator->create("my_great_username"); 

//code: 
class StaffCreatorFactory 
{  
    function __invoke(ContainerInterface $container) 
    { 
     return new StaffCreator(); 
    } 
} 

class StaffCreator 
{ 
    function __construct() 
    { 
     //additional creation parameters possible here 
    } 

    function create(string $username): Staff 
    { 
     return new Staff($username); 
    } 
} 

Steve에 참고 : 만들고 DI를 재사용하기 위해 위의 코드에 Interfaces를 추가 할 수 있습니다. 즉 StaffCreatorInterface, StaffInterface. 필자가 (아직) 인터페이스 재사용을위한 유스 케이스를 갖고 있지 않기 때문에 필자의 경우 간단하게 유지했다.