Magento 2 không hỗ trợ tiêm phụ thuộc vào đặc điểm?


8

Các đặc điểm có thực sự hoạt động với tiêm phụ thuộc trong Magento? Hãy xem xét các mã sau đây:

Lớp học đặc điểm

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

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

Lớp sử dụng đặc điểm

namespace Frame\Slick\Block;

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

Điều này dường như luôn luôn trả về null, tôi rất chắc chắn rằng mọi thứ đang được đưa vào đúng. Đặc điểm có thể thực sự hỗ trợ tiêm phụ thuộc?

EDIT: Ví dụ: nếu bạn thực hiện một di trong hàm tạo đặc điểm và gán nó cho một biến tính trạng và sau đó gọi nó trên lớp sử dụng đặc điểm đó, nó sẽ luôn trả về null. Bất cứ điều gì khác hoạt động tốt.


Chỉ cần một câu hỏi ... "testTrait ()" có trả về null hoặc "$ this -> _ slickHelper" là null không?
Phoenix128_RiccardoT

$ this -> _ slickHelper trả về null, các phương thức khác trong công việc tính trạng chỉ được gán cho các biến tính trạng không hoạt động.
André Ferraz

1
Câu hỏi hay. Tôi giả sử, Magento sử dụng Reflection để kiểm tra các đối số của hàm tạo và điều này hoạt động tốt với các đặc điểm: 3v4l.org/jbVTU - nhưng tôi sẽ phải xem xét kỹ hơn về việc tạo mã để xác minh nó.
Fabian Schmengler

nhưng tại sao bạn muốn sử dụng đặc điểm? Bạn có thể đưa ra một ví dụ thực tế cuộc sống? Có lẽ có một cách đơn giản hơn xung quanh nó
Marius

@Marius Tôi đã tạo mô-đun này hoạt động như một thanh trượt cho Khối CMS, Bán chéo, Sản phẩm (thuộc danh mục cụ thể) và bán lên. Mỗi một trong các lớp khối này mở rộng một lớp khác, ví dụ các sản phẩm mở rộng Magento \ Catalog \ Block \ Product \ ListSản phẩm. Thực sự lý do tại sao tôi sử dụng các đặc điểm là bởi vì nó giải quyết "vấn đề" kiến ​​trúc thừa kế duy nhất của PHP. Cách này có ít sự lặp lại mã.
André Ferraz

Câu trả lời:


2

Tôi đã thử nghiệm bằng cách sử dụng đặc điểm và nó hoạt động tốt.

Đây là đặc điểm của tôi trông như thế nào:

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

Tôi sử dụng nó trong bộ điều khiển như thế này:

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

Và đây là kết quả:

Kết quả kiểm tra tính trạng


0

Tôi chỉ phải đối mặt với điều này bản thân mình. Bài viết ban đầu khá cũ nên bây giờ mọi thứ có thể khác so với khi nó được đăng, tuy nhiên điều tôi thấy là hàm tạo DI hoạt động nhưng nó có một cảnh báo khá lớn.

Nếu tôi sử dụng Trait sau trong mã của mình:

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

và sau đó tiến hành sử dụng đặc điểm đó trong một lớp:

<?php

namespace My\Module;

use \My\Module\Util\LoggerTrait;

class Service
{
    use LoggerTrait;

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

Giao diện logger được tiêm hoàn hảo và mọi thứ hoạt động tốt. TUY NHIÊN, nếu tôi muốn đưa các lớp của riêng mình vào lớp Dịch vụ của mình bằng phương thức constructor. Ví dụ:

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

Trong trường hợp này, phương thức constructor của đặc điểm của tôi không bao giờ được gọi, có nghĩa là thuộc tính $ logger của lớp tôi không bao giờ được đặt. Phải thừa nhận rằng tôi đã không sử dụng các đặc điểm nhiều nên kiến ​​thức của tôi bị hạn chế, nhưng giả định của tôi là điều này là do lớp học của tôi đã ghi đè lên phương thức xây dựng của đặc điểm của tôi. Đây gần như là một điểm dừng hiển thị vì hầu hết các cơ sở mã Magento sử dụng các hàm tạo để tiêm phụ thuộc, ảnh hưởng đến việc loại bỏ việc sử dụng chúng trong các đặc điểm.

Giải pháp thực sự duy nhất tôi có thể thấy là sử dụng ObjectManager trực tiếp để tiêm phụ thuộc vào đặc điểm của bạn:

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

Tuyên bố miễn trừ trách nhiệm: Việc sử dụng ObjectManager trong Magento thường không được khuyến khích nhưng từ những gì tôi có thể thấy trong trường hợp này là lựa chọn thực sự duy nhất. Trong ví dụ của tôi nếu bạn muốn thiết lập một giao diện logger khác trong lớp của mình, bạn vẫn có thể làm điều đó bằng cách đưa nó vào hàm tạo của bạn và ghi đè lên thuộc tính $ logger.


Trong lớp của bạn, bạn đã khai báo 2 __construct, một cái được nhập từ đặc điểm và cái kia trong chính lớp đó. Tuy nhiên, bạn không thể có 2 phương thức có cùng tên trong một lớp. Vì vậy, về cơ bản trong trường hợp của bạn, __constructtrong đặc điểm bị ghi đè bởi __constructchính lớp đó.
Rendy Eko Prastiyo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.