2014-10-10 3 views
6

마침내 PHP에서 특성을 탐색하는 중입니다. 나가 그것을 시도 할 것이라는 점을 나가 생각한 첫번째 장소는 종류로 구성 비트의 주입이다. 내가 DIC를 사용하고 있다면, 내가 설정 객체를 필요로하는 모든 클래스에 같은 코드가있을 수 있습니다 :종속성 주입에 사용되는 PHP 특성 충돌을 방지하는 방법

protected function SetConfig($config) { 
    $this->config = $config; 
} 

protected $config; 

이 사방에 그 상용구 코드를 피하기 위해 특성에 자연 맞는 것 같다, 그래서 이를 만들 수 있습니다 : 다음

trait Config { 
    protected function SetConfig($config) { 
     $this->config = $config; 
    } 

    protected $config; 
} 

을 등처럼 사용 : 위대한

class Foo { 
    use Config; 

    public function __construct() { 
     //can now use $this->config 
    } 
} 

합니다. 이제 내가 로깅, 말, 두 번째 특성을 만들려는 말을하자

trait Logger { 
    protected function SetLogger($logger) { 
     $this->logger = $logger; 
    } 

    protected $logger; 
} 

I는 다음과 같이 사용할 수있는 : 위대한 또한

class Foo { 
    use Logger; 

    public function __construct() { 
     //can now use $this->logger 
    } 
} 

합니다. 이제이 두 가지 특성이 서로 사용되기를 원한다면 문제가 발생합니다.

trait Logger { 
    use Config; 

    protected function SetLogger($logger) { 
     $this->logger = $logger; 
    } 

    protected $logger; 
} 

그러나 상황이 다른 클래스는 이러한 특성을 모두 사용하는 경우에 중단됩니다 :

class Foo { 
    use Config, Logger; 

    public function __construct() { 
     //want to use $this->config and $this->logger 
    } 
} 

을 그것은 로거 클래스는이 일을 의미 주입 된 구성 객체를 가질 필요가 있다는 매우 합리적인 것 같다 물론 이것은 설정 비트가 Foo에서 효과적으로 복제되기 때문에 작동하지 않습니다.

로거 특성에서 use Config; 부분을 제외 할 수 있습니다. 마지막 부분에있을 것입니다. 그러나 일종의 외부 의존성을 만들어내는 것에 따라 이것은 나에게 이상하다고 느낀다. 이미 config 특성이없는 로거를 사용하려면 어떻게해야합니까? 이 솔루션은 또한 IDE (PhpStorm 8)에서 알 수없는 메소드에 대해 경고하고 자동 완성 기능을 제공하지 않아도된다는 것을 의미합니다. @method를 사용하여 이러한 문제를 차례로 해결할 수 있다는 것을 알았지 만 그것은 말하자면 돼지에 립스틱을 넣는 것뿐입니다.

로거에서 설정 비트의 별명을 지정할 수도 있지만 그 역시 문제가 있습니다.

이 모든 것은 약간의 냄새가 있지만, 이것이 나를위한 새로운 패턴이거나 정말 악취가 나는 패턴인지는 아직 알지 못했습니다. 어느 쪽이든, 나는이 접근법을 실제로 작동시키는 최선의 방법이 확실하지 않습니다.

특성에서이 문제를 해결하는 가장 좋은 방법에 대한 조언이 있으십니까? 아니면 DIC 지름길을위한 특성을 피하는 것이 더 좋습니까?

+0

DI에 대해서는 'traits'을 사용하지 않았지만 내가 할 수있는 제안은 당신이 다른 형질을 필요로하는 형질을 가지고 있다면 당신은 그것을 형 대신으로 돌릴 때 이익을 얻을 수 있다는 것입니다. – Crackertastic

+0

로거 특성은 사용할 로깅 수준이나 로그 파일을 쓸 위치를 알기 위해 config가 필요할 수 있습니다. 하지만 실제로이 문제는 단지 사례 일뿐입니다. 보다 광범위하게, 기능 핵심 부분간에 종속성을 갖는 것은 드문 일이 아닙니다. 모든 클래스에서 상용구 코드 (속성 및 설정자)를 사용할 때 이것은 문제가 아니지만 특성과 관련된 문제입니다. 이 경우 Logger 및 Config (위의 Foo)를 사용하는 클래스는 Config의 조각이 복제되기 때문에 치명적인 오류가 발생하기 때문에 Logger에'use Config'를 추가해도 작동하지 않습니다. –

+1

그래서 제가 질문을했습니다. 제가 말했듯이, 그것은 우스꽝스러운 냄새가 나지만, 동시에 특성은 DI에 내재 된 상용구 문제를 푸는 훌륭한 접근법처럼 보입니다. 두 가지를 하나로 묶는 최선의 방법은 무엇입니까? –

답변

3

유용한 방법은 getters와 setters를 사용하는 것입니다. 그러면 다른 특성과 충돌하지 않고 특정 게터가 존재하도록 요구할 수 있습니다.

trait Config { 
    protected function SetConfig($config) { 
     $this->config = $config; 
    } 

    protected function GetConfig() { 
     return $this->config; 
    } 

    protected $config; 
} 

trait Logger { 
    abstract protected function GetConfig(); 

    protected function SetLogger($logger) { 
     $this->logger = $logger; 
    } 

    protected $logger; 
} 

class Baz { 
    use Config, Logger; 

    // ... 

} 

Baz에서 Config 특성은 필요한 추상 방법을 제공하며 Baz는 오류없이 작성됩니다. Logger 만 실수로 사용하면 클래스 Baz에 1 개의 추상 메서드가 포함되어 있으므로 추상 메서드로 선언하거나 나머지 메서드 (Baz :: GetConfig)를 구현해야합니다 (Baz :: GetConfig)

+0

이것은 이상적이지는 않지만 작업을 완료합니다. 버그에 관한 주요한 것들 : 1) 문서가 지저분해진다. (예를 들어 Logger를 보았을 때, GetConfig()가 어디서 왔는지를 어떻게 알 수 있는가?) 2) Logger를 사용하려면 Config를 사용해야한다. 3) 문서화와 관련이 있지만, IDE 코드 완성과 리펙토링 작업을 위해 PHPDoc에 주석을 어떻게 추가 할 수 있습니까? 작업을 완료하는 솔루션에 대한 요점은 있지만이를 수행 할 수있는 진정한 방법이있는 것이 좋습니다. –

+1

후속 조치로서 예약 1과 3이 phpDocumentor 업데이트에서 다루어 져서 특성을보다 잘 처리 할 수 ​​있다는 점을 알고 있습니다. 그러나 클라이언트로 하여금 로거가 사용된다면 Config가 사용되어야한다는 것을 명시 적으로 요구하는 것은 어쨌든 난장판이 될 것이라고 나는 생각한다. 잘 정의 된 몇 가지 경우에서 제대로 작동하는 것을 볼 수 있지만,이 경우 Config와 Logger는 나 자신에게 재사용이 가능한 "벽돌"처럼 느껴집니다. 다시 한번, 클래스가 로거를 사용하지만 구성은 사용하지 않을 가능성이있는 경우 .... –

+0

특성간에 흘러가는 IDE를 아십니까? $ this-> getConfig를 클릭하면, IDE는 trait Config의 메소드 정의가 아닌 추상 정의로 간다. 아마도 IDE가 IDE를 도와주는 phpdoc일까요? – corretge

관련 문제