2016-11-27 3 views
0

종속성 삽입을 사용하는 경우 종속성을 개별적으로 생성자에 전달해야합니까, 아니면 전체 DI 컨테이너를 전달할 수 있습니까?종속성 삽입 - 컨테이너 또는 개별 종속성 삽입?

예를 들어, 나는 'UserRepository'라는 저장소를 가지고 있습니다. 그것은 다음과 같은 방법을 포함 : 나는 Pimple 용기에 통과했기 때문에

<?php 

namespace MyApp\Repositories; 

use \MyApp\Models\User; 

class UserRepository { 

    private $ci; 

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

    public function hashPassword($password) 
    { 
     return password_hash($password, PASSWORD_BCRYPT, [ 
      'cost' => 15 
     ]); 
    } 

    public function create($firstname, $lastname, $email, $password) 
    { 
     $user = User::create([ 
      'firstname' => $firstname, 
      'lastname' => $lastname, 
      'email'  => $email, 
      'password' => $this->hashPassword($password) 
     ]); 

     return $user; 
    } 

    public function activateUser($userID) 
    { 
     $user = User($userID); 
     $user->email_verified = 1; 
     $user->save(); 

     $verification = $user->verification(); 
     $verification->is_used = 1; 
     $verification->validated_at = $this->ci->get('Carbon')::now(); 
     $verification->save(); 
    } 
} 

Carbon 의존성이 가능합니다. 나는 (등록되어있는 한) 이러한 방식으로 모든 의존성에 접근 할 수있다.

난 이런 종류의 DI를 조장하는 Slim3을 사용하고 있습니다. 그러나, Laravel과 같은 응용 프로그램에서는 생성자에 개별적으로 종속성이 전달되는 것을 볼 수 있습니다.

어떤 조언이 필요합니까?

+0

전체 DI 컨테이너를 종속성으로 전달할 때이를 "서비스 로케이터"라고 부르면 좋지 않습니다. – Federkun

+0

@Federkun 감사합니다. 나는 여드름이 서비스 탐지기라고 믿습니다, 그래서 지금 저는 그것에 매달 렸습니다. 나는 두 사람이 다르다는 것을 몰랐다. 혼란스럽지 않은 것 같습니다 : https://www.reddit.com/r/PHP/comments/3x9e48/service_locator_dependency_injection/ – BugHunterUK

+0

아니요, 여드름은 서비스 탐지기가 아니고 서비스 탐지기로 사용할 수 있습니다 _ – Federkun

답변

2

종속성 주입 컨테이너를 클래스에 전달할 때 "Service Locator"라고 부릅니다. Service Locator를 사용하면 클래스가 이고 여전히 종속성을 인스턴스화하는 데 책임이있는이므로 단위 테스트를 수행해야합니다. 그러나 어떻게? 서비스 로케이터가 없으면 개체를 존재할 수 없으며 쉽게 테스트 할 수 없습니다. 생성자에 종속성을 전달하면 해당 객체를 조롱 할 수 있습니다. 클래스에서

이 있습니다 Carbon는 서비스 이름입니다

$verification->validated_at = $this->ci->get('Carbon')::now(); 

. 이제 클래스에 삽입하는 Service Locator가 해당 이름의 서비스를 필요로하고 Carbon\Carbon 클래스의 인스턴스를 반환해야 함을 명심해야합니다. 서비스 로케이터에 누락 된 Carbon 서비스가 있거나 완전히 다른 객체를 반환하는 경우 어떻게해야합니까? 당신은 아무것도 휴식하지 않도록하기 위해이 같은 뭔가를 테스트해야합니다 :

$this->assertInstanceOf(Carbon\Carbon::class, $container->get('Carbon')); 

더 중요, 다른 곳에서 특정 서비스 로케이터 구현을 구현해야 당신이 개체를 다시 사용합니다. DIC에게 개체를 사용하여

더 이상 종속성을 인스턴스화 할 책임을지지 않습니다 :

$container['user.repository'] = function ($c) { 
    return new UserRepository($c['Carbon']); 
}; 

클래스는 더 재사용 및 쓰기 테스트는 더 쉽다.

+0

위대한 설명을 참조하십시오. 마지막 부분은 나를 혼란스럽게합니다. 제 경우에는'dependencies.php' 파일이 있습니다. 마지막 예제에서'user.repository'와 비슷한 설정이 있습니다. 나는'Monolog'의 새로운 인스턴스를 리턴하는'Logger' 컨테이너를 가지고 있습니다.하지만 서비스 나 동작 내에서'$ this-> ci-> get ('Logger');를 사용하여 액세스합니다. 다른 방법으로 Logger에 액세스해야합니까? – BugHunterUK

+1

서비스 로케이터는 반 패턴이 아니므로 심포니 컨트롤러를 작성할 때 자주 사용합니다. 물론, 그것은 의존성을 숨기고 _it는 최상의 방법은 아닙니다 _ 그러나 그것을 실용적인 방법입니다. 그것이 의미가있는 곳에 사용하십시오. – Federkun