2017-12-19 14 views
2

User 모델에 사용 된 TimezoneTrait이 있습니다. 또한 서비스 제공 업체를 통해로드와 결합이 잘되어야하므로 모든 클래스에서 좋은 작동하는 UserRepositoryInterface 있습니다특성 생성자의 Laravel 전달 인수

public function register() 
{ 
    $this->app->bind(UserRepositoryInterface::class, UserRepository::class); 
} 

public function provides() 
{ 
    return [ 
     UserRepositoryInterface::class, 
    ]; 
} 

지금 내가 가지고있는 문제는 내가 너무 내 특성에서 그 저장소를 사용해야한다는 것입니다 나는 자연이 한 :

private $userRepository; 

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

을하지만 덤프 저장소가 null 것을 보여준다. 형질에 의존성을 주입 할 수 없습니까?

+0

는'$ userRepository를 보호 선포'수는 –

+0

아니, 아무것도에게 내가 아는 한, 그들은'에 use'ed있는 클래스와 함께 주입 할 수없는 – Norgul

+0

특색을하지 않습니다하지만 아무것도 작동하지 않습니다. 다른 클래스를 주입하는 클래스의 특성을 사용하지 못하게합니다. – Andrew

답변

2

특성 내에서 __constructor을 정의하는 것은 실제로 잘못되었습니다. 아니면 그냥 나쁜 디자인. Constructors should be specific to a class to which they belong, 형질이 아닙니다. 또 다른 문제는 Model 클래스에서 특성을 가져 오는 것입니다. 즉, 구체적으로 a trait in a model is loaded에 대한 규칙을 따라야 함을 의미합니다.

모델의 입력 단계에서 가져온 특성을 클래스 내에서 반복적으로 검색하고 자동으로 boot{TraitNameHere} 명명 규칙을 사용하는 메서드를 호출합니다. 이는 모델의 특성이 Laravel의 의존성 주입주기와 관련이 없음을 증명합니다.

Laravel 전역 도우미를 사용하여 컨테이너 내에 저장된 인스턴스 (예 : App::make(DefinedKeyHere))를로드 할 수 있습니다. 그런 다음 지정된 인스턴스를 정적 속성에 저장하여 런타임이 끝날 때까지 유지하고 리콜 방법이 static이기 때문에 유지합니다.

trait TimezoneTrait 
{ 
    protected static $userRepository; 

    protected static function bootTimezoneTrait() 
    { 
     static::$userRepository = \App::make(UserRepositoryInterface::class); 
    } 
} 

현재 글로벌 도우미 사용을 피하려면 모델 부팅 이벤트를 수신하는 것이 좋습니다. EventServiceProvider 내부 예,

Event::listen('eloquent.booting:*', function (Model $model) { 
    $model->setUserRepository($this->app[UserRepositoryInterface::class]); 
}); 

그런 다음 특성은
trait TimezoneTrait 
{ 
    protected static $userRepository; 

    public function static setUserRepository(UserRepositoryInterface $userRepository) 
    { 
     static::$userRepository = $userRepository; 
    } 
} 

내가 setUserRepository 정적으로 정의 된 메모를 가지고,하지만 당신은 너무, 그것은 비 정적 만들 수있을 것이다.

모델 이벤트에 대해 조금 확장하면 모델에는 관련 작업을 수행 할 때마다 여러 가지 이벤트가 발생합니다. Laravel 5.5에서

예 이벤트,

public function getObservableEvents() 
{ 
    return array_merge(
     [ 
      'creating', 'created', 'updating', 'updated', 
      'deleting', 'deleted', 'saving', 'saved', 
      'restoring', 'restored', 
     ], 
     $this->observables 
    ); 
} 

그리고 bootingbooted이다 그 (또한 직렬화를) 인스턴스화 할 때 해고 된 다른 두 개의 기본 이벤트. 그리고 이벤트를 발생시키는 데 사용되는 메소드는 이벤트 이름을 확인합니다.

protected function fireModelEvent($event, $halt = true) 
{ 
    // ... 

    return ! empty($result) ? $result : static::$dispatcher->{$method}(
     "eloquent.{$event}: ".static::class, $this 
    ); 
} 
+0

부팅과 구성의 차이점은 무엇입니까? 생성자는 클래스가 인스턴스화 될 때만 호출되지만 모든 서비스 공급자가 등록 된 후에는 초기에 boot가 호출됩니다. 이는 부팅이 클래스가 인스턴스화되었는지 여부와 관계없이 독립적으로 호출된다는 의미입니까? – Norgul

+0

그것은'boot'와는 다른데, 당신이 참조하는 것은 응용 프로그램의'boot'strapping입니다. 그러나 이것은 단지 모델에서만 일어나는'boot'입니다. 일단 모델이 인스턴스화되면,이'boot '는 위에서 언급 한 것처럼, 전체 특성을 재귀 적으로 호출하고 정적 이벤트를 적용하는 등의 작업을합니다. 일단'부팅 '을하면,'부팅'단계가 이미 완료되었음을 알리는 유지 된 값을 저장합니다. 따라서 다시 새로운 모델을 생성 할 때마다 (예 :'Model :: :: create' 등), 어려운 단계의 메모리를 피할 수 있습니다. – Chay22