Lo stavo affrontando da solo. Il post originale è piuttosto vecchio, quindi le cose potrebbero essere diverse ora rispetto a quando è stato pubblicato, tuttavia quello che ho scoperto è che il costruttore DI funziona ma ha un avvertimento piuttosto grande.
Se uso il seguente tratto nel mio codice:
<?php
namespace My\Module\Util;
use Psr\Log\LoggerInterface;
trait LoggerTrait
{
protected $logger;
public function __construct(
LoggerInterface $logger
) {
$this->logger = $logger;
}
/**
* @return Logger
*/
public function getLogger()
{
return $this->logger;
}
/**
* @param Logger $logger
*/
public function setLogger($logger)
{
$this->logger = $logger;
}
}
e quindi procedere con l'uso di quel tratto in una classe:
<?php
namespace My\Module;
use \My\Module\Util\LoggerTrait;
class Service
{
use LoggerTrait;
public function doSomething() {
$this->getLogger()->log('Something was done!');
}
}
L'interfaccia del logger viene iniettata perfettamente e tutto funziona bene. TUTTAVIA, se voglio iniettare le mie classi nella mia classe di servizio usando il metodo del costruttore. Per esempio:
<?php
namespace My\Module;
use \My\Module\Util\LoggerTrait;
class Service
{
use LoggerTrait;
public function __construct(
\Some\Other\Class $class
) {
$this->other = $class;
}
public function doSomething() {
$this->getLogger()->log('Something was done!');
}
}
In questo caso il metodo di costruzione della mia caratteristica non viene mai chiamato, il che significa che la proprietà $ logger della mia classe non viene mai impostata. Devo ammettere che non ho usato molto i tratti, quindi la mia conoscenza è un po 'limitata, ma la mia ipotesi è che ciò è dovuto al fatto che la mia classe ha scavalcato il metodo di costruzione del mio tratto. Questo è praticamente un punto fermo poiché la maggior parte della base di codice Magento utilizza costruttori per iniettare dipendenze, escludendo in modo affettivo il loro uso nei tratti.
L'unica vera soluzione che posso vedere è utilizzare l'ObjectManager direttamente per iniettare le dipendenze dei tratti:
<?php
namespace My\Module\Util;
use Psr\Log\LoggerInterface;
trait LoggerTrait
{
protected $logger;
/**
* @return Logger
*/
public function getLogger()
{
if (is_null($this->logger)) {
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->logger = $objectManager->create('Psr\Log\LoggerInterface');
}
return $this->logger;
}
/**
* @param Logger $logger
*/
public function setLogger($logger)
{
$this->logger = $logger;
}
}
Disclaimer: l'uso di ObjectManager in Magento è generalmente sconsigliato, ma da quello che vedo in questo caso è l'unica vera opzione. Nel mio esempio, se si desidera impostare un'interfaccia logger diversa nella propria classe, è comunque possibile farlo iniettandola nel proprio costruttore e sovrascrivendo la proprietà $ logger delle classi.