Яка різниця між типом і virtualType


41

У тому, di.xmlщо поставляється з Magento2, є вузол typeі вузол virtualType. Мої запитання: що це таке, virtualTypeі в якому випадку його слід використовувати замість type?

У деяких місцях це виглядає як символічне посилання або переписати:

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

Там, де один повний шлях змінюється на інший, але в інших місцях він, як видається, використовується як спосіб визначення коротшого псевдоніма.

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

3
Я поняття не маю (поки) , що вони навіть означати , але ви можете почати копати звідси: Magento\Framework\ObjectManager\Config\Mapper\Dom::convert. Там switchдесь є заява.
Маріус

Дякую @Marius, мені також цікаво, чи lessFileSourceBaseобмежений він xml або чи можна це використовувати і зовні. Здогадайтесь, я краще перекопаюся.
Девід Маннерс

Відповіді:


84

Віртуальні типи - це спосіб ввести різні залежності в існуючі класи, не впливаючи на інші класи.

Наприклад, Magento\Framework\Session\Storageклас приймає $namespaceаргумент у своєму конструкторі, який за замовчуванням має значення 'default', і ви можете використовувати typeвизначення для зміни простору імен на 'core'.

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

Вищенаведений конфігурація зробив би так, що всі екземпляри Magento\Framework\Session\Storageмають простір імен 'core'. Використання віртуального типу дозволяє створити еквівалент підкласу, де лише підклас має змінені значення аргументу.

У кодовій базі ми бачимо наступні дві конфігурації:

<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>

Перший фрагмент створює віртуальний тип, для Magento\Core\Model\Session\Storageякого змінює простір імен, а другий вводить у віртуальний тип Magento\Framework\Session\Generic. Це дозволяє Magento\Framework\Session\Genericналаштувати, не впливаючи на інші класи, які також оголошують залежністьMagento\Framework\Session\Storage


Дуже дякую @Chris нарешті, я знайшов логічне обгрунтування
Suman-PHP4U

Це була проста і найкраща демонстрація.
Умар

Ця відповідь краще, ніж офіційний документ Magento
Suman-PHP4U

<type>використовує віртуальний клас, який насправді не існує. Таким чином, модифікація аргументу virtualTypeнабуде чинності лише тоді, коли ініціалізується клас, що використовує virtualType, що є Magento\Framework\Session\Genericу прикладі
Аріф Ахмад

21

Ще один спосіб зрозуміти віртуальні типи -

Скажімо, у вас клас \Class1, у якого є такий конструктор -

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

І \Class2має наступний конструктор -

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

Тепер ви хочете змінити тип $argOfClass2з \Class3на \Class4, але лише тоді, коли \Class2він використовується як $argOfClass1.

"Старий" спосіб зробити це - додати наступне в di.xml-

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

де \Class5таке:

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

Замість використання цього способу ви можете використовувати віртуальні типи для цього, додавши наступне до 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>

Як бачите, використовуючи віртуальний тип, ви зберегли роботу над створенням Class5.

Для подальшого ознайомлення пропоную прочитати статтю Alan Storm щодо віртуальних типів у Magento2 - http://alanstorm.com/magento_2_object_manager_virtual_types/


1
хороша розгортання,
Ананд Онтігері

Легко зрозуміти. Дякуємо, що поділилися таким основним прикладом.
Кальян Чакраварті V

10

У цьому ж di.xmlфайлі я виявив, що lessFileSourceBaseпередається як аргумент, lessFileSourceBaseFilteredякий передається як аргумент, lessFileSourceBaseSortedякий передається як аргумент типу Magento\Framework\Less\File\Collector\Aggregated.

Я не знайшов жодного іншого явища lessFileSourceBase(або lessFileSource) в іншому файлі, крім di.xmlосновного модуля. Тільки в деяких файлах кешу, але вони не важливі.

Я думаю, якщо ви не збираєтесь використовувати віртуальний тип у класі PHP, а лише у diфайлах xml, тоді вам не потрібно робити це схожим на ім'я класу, і ви можете використовувати псевдонім.

Але це лише чисті спекуляції.
Буде "цікаво" спробувати створити клас і ввести в його конструктор екземпляр, lessFileSourceBaseщоб побачити, як він поводиться.


1
ви пропустили цитати навколо слова fun;)
Девід Маннерс

1
@DavidManners. Правильно. Я полагодив це. :)
Маріус

@Marius: Якщо ви зміните \Magento\Framework\Session\Genericвихідний файл, щоб залежати від Magento\Core\Model\Session\Storageнього, StorageInterfaceвам слід отримати виняток "Class Magento \ Core \ Model \ Session \ Storage не існує". Причина полягає в тому, що ObjectManager не створює екземпляр virtualType, а просто використовує його для визначення аргументів для конструктора конкретного типу, на який посилається визначення virtualType ( Magento\Framework\Session\Storageдля вищевказаного прикладу).
Chris O'Toole

Можна побачити це на Фабриці , де $requestedTypeпредставляє віртуальний тип і використовується для збору аргументів, але $typeце конкретний тип, на який virtualType відображається і використовується для виклику інстанціфікації об'єкта.
Chris O'Toole

Отже, навіть якщо він lessFileSourceBaseбув у більш простому стилі імен \ class type, він не дозволяв би прямого посилання іншим класом php, лише для ін'єкції через di.xml
Chris O'Toole
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.