Avoiding collision of PHP properties used for dependency injection

I will finally get around learning traits in PHP. The first thing I thought I would try is to inject config bits into classes. If I use DIC, I can have code like this in any class that needs a configuration file:

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

This seems like a natural attachment to traits to avoid having this boilerplate code everywhere, so I could create this:

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

and then use it like this:

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

It's great. Now let me say that I want to create a second trait, say, for registration:

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

What can I use as follows:

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

Also great. Now the problem arises if these two features want to use each other. It seems quite reasonable that an installed configuration object should be installed for the registrar class, which means doing this:

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

But then everything will break when another class uses both of these features:

 class Foo { use Config, Logger; public function __construct() { //want to use $this->config and $this->logger } } 

This, of course, does not work, because the configuration bits are effectively duplicated in Foo.

I could just leave a piece of use Config; from the Logger trait, knowing that he will be there in the end. But it seems strange to me, because it creates a kind of external dependence. What if I want to use Logger somewhere that does not already have a configuration? This solution also means that I need to migrate my IDE (PhpStorm 8), warning me about unknown methods and not suggesting autocomplete. I understand that I could fix these problems, in turn, using @method, but it's just lipstick on pigs, so to speak.

I could also use the configuration bits in Logger, but this is also problematic.

It all smells a bit, but I still haven't figured it out because it is a new template for me or it is really a smelly template. In any case, I'm not sure if the best way to make this approach really work.

Any tips on the best way to solve this problem in outline? Or is it better to avoid traits to reduce DIC?

+6
source share
1 answer

The method I found useful is using getters as well as setters. This allows you to require a specific getter to exist without contradicting other attributes.

 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; // ... } 
In Baz, the Config property provides the required abstract method, and Baz is compiled without errors. If you mistakenly use Logger, you get Fatal Error: Class Baz contains 1 abstract method and therefore must be declared abstract or implement the remaining methods (Baz :: GetConfig)
+3
source

Source: https://habr.com/ru/post/976587/


All Articles