Magento 2 Tidak Mendukung Injeksi Ketergantungan pada Ciri-Ciri?

8

Apakah ciri-ciri sebenarnya berfungsi dengan injeksi ketergantungan pada Magento? Pertimbangkan kode berikut:

Kelas Sifat

namespace Frame\Slick\Block;
use Frame\Slider\Slick\Block\Data as Helper

trait Slick
{
   protected $_slickHelper;
   public function __construct(Helper $slickHelper) 
   {
     $this->_slickHelper = $slickHelper;
   }
}

Kelas menggunakan sifat tersebut

namespace Frame\Slick\Block;

class Product ListProduct implements BlockInterface 
{
   use Slick;
   public function testTrait()
   {
      return $this->_slickHelper->getHelloWorld();
   }
}

Ini sepertinya selalu mengembalikan nol, saya yakin semuanya dimasukkan dengan benar. Bisakah sifat benar-benar mendukung injeksi ketergantungan?

EDIT: Sebagai contoh jika Anda melakukan suatu di di trait constructor dan menugaskannya ke variabel trait dan kemudian memanggilnya pada kelas yang menggunakan trait, ia akan selalu mengembalikan null. Ada lagi yang berfungsi dengan baik.

André Ferraz
sumber
Hanya satu pertanyaan ... apakah "testTrait ()" mengembalikan nol atau "$ this -> _ slickHelper" adalah nol?
Phoenix128_RiccardoT
$ this -> _ slickHelper mengembalikan null, metode lain dalam pekerjaan sifat hanya di yang ditugaskan ke variabel sifat tidak berfungsi.
André Ferraz
1
Pertanyaan bagus. Saya berasumsi, Magento menggunakan Refleksi untuk memeriksa argumen konstruktor dan ini bekerja dengan baik dengan ciri-ciri: 3v4l.org/jbVTU - tetapi saya harus melihat lebih dekat pada pembuatan kode untuk memverifikasinya.
Fabian Schmengler
tetapi mengapa Anda ingin menggunakan sifat? Bisakah Anda memberi contoh kehidupan nyata? Mungkin ada cara yang lebih sederhana di sekitarnya
Marius
@Marius saya membuat modul ini yang bertindak sebagai slider untuk Blok CMS, Cross menjual, Produk (dari kategori tertentu) dan lebih tinggi menjual. Masing-masing dari kelas blok ini memperluas kelas lain misalnya produk memperluas Magento \ Catalog \ Block \ Product \ ListProduct. Sungguh alasan mengapa saya menggunakan sifat-sifat adalah karena ia memecahkan arsitektur "masalah" warisan PHP tunggal. Dengan cara ini ada sedikit pengulangan kode.
André Ferraz

Jawaban:

2

Saya telah diuji menggunakan sifat dan itu berfungsi dengan baik.

Ini adalah sifat saya:

<?php

namespace ProjectName\ModuleName\Controller\Adminhtml;

use Magento\Backend\App\Action\Context;
use ProjectName\ModuleName\Model\ResourceModel\Distributor\CollectionFactory as DistributorCollectionFactory;

trait DistributorTrait
{
    protected $distributorCollectionFactory;

    public function __construct(
        Context $context,
        DistributorCollectionFactory $distributorCollectionFactory
    )
    {
        parent::__construct($context);

        $this->distributorCollectionFactory = $distributorCollectionFactory;
    }
}

Saya menggunakannya dalam controller seperti ini:

<?php

namespace ProjectName\ModuleName\Controller\Adminhtml\Distributor;

use Magento\Backend\App\Action;
use ProjectName\ModuleName\Controller\Adminhtml\DistributorTrait;

class Index extends Action
{
    use DistributorTrait;

    public function execute()
    {
        dump($this->distributorCollectionFactory->create()->getItems());exit;
    }
}

Dan inilah hasilnya:

Hasil Uji Sifat

Rendy Eko Prastiyo
sumber
0

Saya hanya menghadapi ini sendiri. Posting asli cukup tua sehingga hal-hal mungkin berbeda sekarang daripada ketika diposting, namun yang saya temukan adalah bahwa konstruktor DI berfungsi tetapi memiliki peringatan yang cukup besar.

Jika saya menggunakan Ciri berikut dalam kode saya:

<?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;
    }
}

dan kemudian lanjutkan untuk menggunakan sifat itu di kelas:

<?php

namespace My\Module;

use \My\Module\Util\LoggerTrait;

class Service
{
    use LoggerTrait;

    public function doSomething() {
        $this->getLogger()->log('Something was done!');
    }
}

Antarmuka logger disuntikkan dengan sempurna dan semuanya berfungsi dengan baik. NAMUN, jika saya ingin menyuntikkan kelas saya sendiri ke kelas Layanan saya menggunakan metode konstruktor. Misalnya:

<?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!');
    }
}

Dalam hal ini metode konstruktor sifat saya tidak pernah dipanggil, artinya properti $ logger dari kelas saya tidak pernah disetel. Memang saya belum banyak menggunakan sifat sehingga pengetahuan saya agak terbatas, tetapi asumsi saya adalah ini karena kelas saya telah menimpa metode konstruktor sifat saya. Ini cukup banyak sebagai penghenti acara karena sebagian besar basis kode Magento menggunakan konstruktor untuk menyuntikkan ketergantungan, secara efektif mengesampingkan penggunaannya dalam sifat.

Satu-satunya solusi nyata yang bisa saya lihat adalah dengan menggunakan ObjectManager secara langsung untuk menyuntikkan ketergantungan sifat Anda:

<?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;
    }
}

Penafian: Penggunaan ObjectManager di Magento pada umumnya tidak disarankan tetapi dari apa yang saya lihat dalam kasus ini adalah satu-satunya pilihan nyata. Dalam contoh saya jika Anda ingin mengatur antarmuka logger yang berbeda di kelas Anda, Anda masih bisa melakukannya dengan menyuntikkannya di konstruktor Anda dan menimpa properti $ logger kelas.

Andrew Kett
sumber
Di kelas Anda, Anda telah mendeklarasikan 2 __construct, yang satu diimpor dari sifat, dan yang lainnya di kelas itu sendiri. Namun, Anda tidak dapat memiliki 2 metode dengan nama yang sama di kelas tunggal. Jadi pada dasarnya dalam kasus Anda, __constructsifat itu ditimpa oleh __constructdi dalam kelas itu sendiri.
Rendy Eko Prastiyo