W końcu wracam do odkrywania cech w PHP. Pierwsze miejsce, w którym myślałem, że wypróbuję to wtrysk bitów konfiguracyjnych na klasy. Jeśli używam DIC, może mam kod jak to w każdej klasie, która potrzebuje obiekt config:Jak uniknąć zderzeń z cechami PHP używanymi do iniekcji zależności
protected function SetConfig($config) {
$this->config = $config;
}
protected $config;
Wydaje się to naturalne dopasowanie do cech, aby uniknąć konieczności ten kod szablonowe wszędzie, więc może tworzyć w ten sposób:
trait Config {
protected function SetConfig($config) {
$this->config = $config;
}
protected $config;
}
a następnie używać go tak:
class Foo {
use Config;
public function __construct() {
//can now use $this->config
}
}
to świetnie. Teraz załóżmy, że chcę utworzyć drugą cechę, powiedzmy, do logowania:
trait Logger {
protected function SetLogger($logger) {
$this->logger = $logger;
}
protected $logger;
}
której mogę użyć takiego:
class Foo {
use Logger;
public function __construct() {
//can now use $this->logger
}
}
również wspaniałe. Teraz problem pojawia się, jeśli te dwie cechy chcą się nawzajem wykorzystać. Wydaje się całkiem rozsądne, że klasa rejestrator musiałaby mieć obiekt config wstrzykiwany, co oznacza ten sposób:
trait Logger {
use Config;
protected function SetLogger($logger) {
$this->logger = $logger;
}
protected $logger;
}
Ale potem wszystko pęknie, gdy inna klasa używa obu tych cech:
class Foo {
use Config, Logger;
public function __construct() {
//want to use $this->config and $this->logger
}
}
To oczywiście nie działa, ponieważ bity konfiguracyjne są skutecznie duplikowane w Foo.
Mogę po prostu pominąć element use Config;
z cechy Logger, wiedząc, że będzie tam na końcu. Ale wydaje mi się to dziwne, ponieważ tworzy rodzaj zewnętrznej zależności. Co się stanie, jeśli chcę użyć Logger w miejscu, które nie ma jeszcze cechy konfiguracyjnej? To rozwiązanie oznacza również, że muszę cierpieć z powodu mojego IDE (PhpStorm 8) ostrzegającego mnie przed nieznanymi metodami, a nie oferującego autouzupełniania. Zdaję sobie sprawę, że mogę rozwiązać te problemy po kolei, używając metody @method, ale to po prostu umieszczenie szminki na świni, że tak powiem.
Mogę również pseudo konfigurować bitów w Logger, ale to również problematyczne.
Wszystko to ma w sobie trochę zapachu, ale nie doszedłem jeszcze do tego, czy to dlatego, że jest to dla mnie nowy wzór, czy też naprawdę jest śmierdzący wzór. Tak czy siak, nie jestem pewien, jaki jest najlepszy sposób, aby to podejście faktycznie zadziałało.
Wszelkie porady dotyczące najlepszego sposobu rozwiązania tego problemu pod względem cech? A może lepiej unikać cech skracania DIC?
Nigdy nie użyłem "cech" dla DI, ale jeden Sugeruję, że mogę zrobić, że jeśli masz cechy, które wymagają innych cech, możesz skorzystać z zamiany ich na klasy. – Crackertastic
Cecha rejestratora może potrzebować konfiguracji, aby wiedzieć, jakiego poziomu rejestrowania użyć lub gdzie zapisać pliki dziennika. Ale tak na prawdę, pytanie dotyczy czegoś więcej niż tylko tej sprawy - to tylko przykład. Mówiąc szerzej, nie jest rzadkością posiadanie zależności między rdzeniowymi funkcjami. Gdy używasz kodu standardowego (własności i setera) w każdej klasie, nie jest to problemem, ale jest to problem z cechami. W takim przypadku dodanie polecenia 'use Config' do programu Logger nie będzie działać, ponieważ klasa korzystająca zarówno z Logger, jak i Config (powyżej, Foo) wygeneruje błędy krytyczne, ponieważ elementy z Config są zduplikowane. –
Dlatego zadałem to pytanie. Jak już powiedziałem, ma zabawny zapach, ale jednocześnie wydaje się, że cechy są świetnym podejściem do rozwiązania problemu z płytkami charakterystycznymi dla DI. Jakie jest najlepsze podejście do połączenia tych dwóch elementów? –