Sự khác biệt giữa loại và virtualType là gì


41

Trong di.xmlđó đi kèm với Magento2 có một nút typevà một nút virtualType. Câu hỏi của tôi là cái này là gì virtualTypevà trong trường hợp nào nó nên được sử dụng thay vì type?

Ở một số nơi, nó trông giống như một liên kết tượng trưng hoặc viết lại:

<virtualType name="Magento\Core\Model\Session\Storage" type="Magento\Framework\Session\Storage">

Khi một đường dẫn đầy đủ được thay đổi thành một đường dẫn khác nhưng ở những nơi khác, nó dường như được sử dụng như một cách để xác định bí danh ngắn hơn.

<virtualType name="lessFileSourceBase" type="Magento\Framework\View\File\Collector\Base">

3
Tôi không biết (chưa) ý nghĩa của chúng là gì nhưng bạn có thể bắt đầu đào từ đây : Magento\Framework\ObjectManager\Config\Mapper\Dom::convert. Có một switchtuyên bố trong đó ở đâu đó.
Marius

Cảm ơn @Marius, tôi cũng tự hỏi liệu lessFileSourceBasecó bị giới hạn trong xml hay nếu điều đó cũng có thể được sử dụng bên ngoài. Đoán tôi tốt hơn nên đào.
David Manners

Câu trả lời:


83

Các loại ảo là một cách để đưa các phụ thuộc khác nhau vào các lớp hiện có mà không ảnh hưởng đến các lớp khác.

Ví dụ, Magento\Framework\Session\Storagelớp lấy một $namespaceđối số trong hàm tạo của nó, mặc định là giá trị 'mặc định' và bạn có thể sử dụng typeđịnh nghĩa để thay đổi không gian tên thành 'lõi'.

<type name="Magento\Framework\Session\Storage">
    <arguments>
        <argument name="namespace" xsi:type="string">core</argument>
    </arguments>
</type>

Cấu hình trên sẽ làm cho nó sao cho tất cả các phiên bản Magento\Framework\Session\Storagecó không gian tên là 'lõi'. Sử dụng một loại ảo cho phép tạo ra tương đương với một lớp con, trong đó chỉ có lớp con có các giá trị đối số bị thay đổi.

Trong cơ sở mã, chúng ta thấy hai cấu hình sau:

<virtualType name="Magento\Core\Model\Session\Storage" type="Magento\Framework\Session\Storage">
    <arguments>
        <argument name="namespace" xsi:type="string">core</argument>
    </arguments>
</virtualType>

<type name="Magento\Framework\Session\Generic">
    <arguments>
        <argument name="storage" xsi:type="object">Magento\Core\Model\Session\Storage</argument>
    </arguments>
</type>

Đoạn mã đầu tiên tạo ra một loại ảo Magento\Core\Model\Session\Storagelàm thay đổi không gian tên và loại thứ hai đưa loại ảo vào Magento\Framework\Session\Generic. Điều này cho phép Magento\Framework\Session\Genericđược tùy chỉnh mà không ảnh hưởng đến các lớp khác cũng khai báo một phụ thuộc vàoMagento\Framework\Session\Storage


Cảm ơn rất nhiều @Chris cuối cùng cũng có một số biện minh hợp lý mà tôi đã tìm thấy
Suman-PHP4U

Đó là đơn giản và trình diễn tốt nhất.
Umar

Câu trả lời này tốt hơn sau đó là tài liệu chính thức của Magento
Suman-PHP4U

<type>đang sử dụng một lớp ảo không thực sự tồn tại. Bằng cách này, việc sửa đổi đối số virtualTypesẽ chỉ có hiệu lực khi lớp sử dụng virtualType được khởi tạo Magento\Framework\Session\Generictrong ví dụ
Arif Ahmad

21

Một cách khác để hiểu các loại ảo -

Giả sử bạn có một lớp \Class1, có hàm tạo sau -

public function __construct(\Class2 $argOfClass1){...}

\Class2có các hàm tạo sau -

public function __construct(\Class3 $argOfClass2){...}

Bây giờ, bạn muốn thay đổi loại $argOfClass2từ \Class3thành \Class4, nhưng chỉ khi \Class2được sử dụng như $argOfClass1.

Cách "cũ" để làm điều đó sẽ là thêm vào sau di.xml-

<type name="Class1">
    <arguments>
         <argument name="argOfClass1" xsi:type="object">Class5</argument>
    </arguments>
</type>

nơi nào \Class5sau đây:

class \Class5 extends \Class2{
    public function __construct(\Class4 $argOfClass2){...}
}

Thay vì sử dụng cách này, bạn có thể sử dụng các loại ảo để thực hiện tương tự, bằng cách thêm các mục sau vào di.xml:

<virtualType name="Class5" type="Class2">
    <arguments>
        <argument name="argOfClass2" xsi:type="string">Class4</argument>
    </arguments>
</virtualType>

<type name="Class1">
    <arguments>
         <argument name="argOfClass1" xsi:type="object">Class5</argument>
    </arguments>
</type>

Như bạn có thể thấy, sử dụng loại ảo đã giúp bạn tiết kiệm công việc tạo ra Class5.

Để tham khảo thêm, tôi khuyên bạn nên đọc bài viết của Alan Storm về các loại ảo trong Magento2 - http://alanstorm.com/magento_2_object_manager_virtual_types/


1
đánh giá cao,
Anand Onigeri

Dễ hiểu. Cảm ơn đã chia sẻ một ví dụ cơ bản như vậy.
Kalyan Chakravarthi V

10

Trong cùng một di.xmltệp tôi thấy rằng nó lessFileSourceBaseđược truyền dưới dạng đối số cho lessFileSourceBaseFilterednó được truyền dưới dạng đối số cho lessFileSourceBaseSortednó được truyền dưới dạng đối số cho kiểu Magento\Framework\Less\File\Collector\Aggregated.

Tôi không tìm thấy sự xuất hiện nào khác của lessFileSourceBase(hoặc lessFileSource) trong một tệp khác ngoại trừ di.xmltừ mô-đun lõi. Chỉ trong một số tệp bộ nhớ cache nhưng chúng không quan trọng.

Tôi đoán rằng nếu bạn sẽ không sử dụng loại ảo trong một lớp PHP, nhưng chỉ trong các ditệp xml thì bạn không bắt buộc phải làm cho nó trông giống như một tên lớp và bạn có thể sử dụng bí danh.

Nhưng đây chỉ là suy đoán thuần túy.
Sẽ rất "vui" khi cố gắng tạo một lớp và thêm vào hàm tạo của nó một ví dụ lessFileSourceBaseđể xem cách nó hoạt động.


1
bạn đã bỏ lỡ các trích dẫn xung quanh từ vui nhộn;)
David Manners

1
@DavidManners. Đúng. Tôi sửa nó rồi. :)
Marius

@Marius: Nếu bạn thay đổi \Magento\Framework\Session\Generictệp nguồn thành phụ thuộc Magento\Core\Model\Session\Storagethay vì StorageInterfacebạn sẽ có ngoại lệ 'Class Magento \ Core \ Model \ Session \ Storage không tồn tại'. Lý do là ObjectManager không tạo ra một thể hiện của VirtualType, mà chỉ sử dụng điều đó để xác định đối số nào sẽ cung cấp cho hàm tạo của loại cụ thể được tham chiếu bởi định nghĩa virtualType ( Magento\Framework\Session\Storageví dụ ở trên).
Chris O'Toole

Có thể thấy điều này trong Factory , nơi $requestedTypeđại diện cho loại ảo và được sử dụng để thu thập các đối số, nhưng $typelà loại cụ thể mà virtualType ánh xạ tới và được sử dụng cho cuộc gọi khởi tạo đối tượng.
Chris O'Toole

Vì vậy, ngay cả khi lessFileSourceBasetheo kiểu không gian tên lớp \ nhiều hơn, nó sẽ không cho phép tham chiếu trực tiếp bởi một lớp php khác, chỉ để tiêm qua di.xml
Chris O'Toole
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.