Jaka jest różnica między typem a virtualType

41

W tym, di.xmlco pochodzi z Magento2, jest węzeł typei węzeł virtualType. Moje pytania brzmią: co to jest virtualTypeiw jakim przypadku należy go użyć type?

W niektórych miejscach wygląda jak symboliczny link lub przepisać:

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

Tam gdzie jedna pełna ścieżka zostaje zamieniona na inną, ale w innych miejscach wydaje się, że jest używana jako sposób na zdefiniowanie krótszego aliasu.

<virtualType name="lessFileSourceBase" type="Magento\Framework\View\File\Collector\Base">
David Manners
źródło
3
Nie mam pojęcia (jeszcze), co w ogóle znaczy, ale można zacząć kopać stąd: Magento\Framework\ObjectManager\Config\Mapper\Dom::convert. switchGdzieś tam jest wypowiedź.
Marius
Dzięki @Marius, zastanawiam się również, czy lessFileSourceBasejest ograniczony do xml, czy może być również używany na zewnątrz. Chyba lepiej zacznę kopać.
David Manners,

Odpowiedzi:

84

Typy wirtualne są sposobem na wstrzyknięcie różnych zależności do istniejących klas bez wpływu na inne klasy.

Na przykład Magento\Framework\Session\Storageklasa pobiera $namespaceargument w swoim konstruktorze, który przyjmuje domyślną wartość „default”, i możesz użyć typedefinicji, aby zmienić przestrzeń nazw na „core”.

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

Powyższa konfiguracja sprawiłaby, że wszystkie wystąpienia Magento\Framework\Session\Storagemiałyby przestrzeń nazw „core”. Użycie typu wirtualnego pozwala na utworzenie odpowiednika podklasy, w której tylko podklasa ma zmienione wartości argumentów.

W bazie kodu widzimy następujące dwie konfiguracje:

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

Pierwszy fragment tworzy typ wirtualny, dla Magento\Core\Model\Session\Storagektórego zmienia przestrzeń nazw, a drugi wstrzykuje typ wirtualny Magento\Framework\Session\Generic. Pozwala to Magento\Framework\Session\Genericna dostosowanie bez wpływu na inne klasy, które również deklarują zależnośćMagento\Framework\Session\Storage

Chris O'Toole
źródło
Wielkie dzięki @Chris w końcu znalazłem logiczne uzasadnienie
Suman-PHP4U
To była prosta i najlepsza demonstracja.
Umar
Ta odpowiedź jest lepsza niż oficjalny dokument Magento
Suman-PHP4U
<type>używa klasy wirtualnej, która tak naprawdę nie istnieje. W ten sposób modyfikacja argumentu virtualTypewejdzie w życie tylko wtedy, gdy zainicjowana zostanie klasa używająca virtualType, co jest Magento\Framework\Session\Genericw przykładzie
Arif Ahmad
21

Kolejny sposób na zrozumienie typów wirtualnych -

Powiedzmy, że masz klasę \Class1, która ma następujący konstruktor -

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

I \Class2ma następujący konstruktor -

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

Teraz chcesz zmienić typ $argOfClass2z \Class3na \Class4, ale tylko wtedy, gdy \Class2jest używany jako $argOfClass1.

„Starym” sposobem na to byłoby dodanie następujących elementów w di.xml-

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

gdzie \Class5jest:

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

Zamiast korzystać z tego sposobu, możesz użyć typów wirtualnych, aby osiągnąć to samo, dodając następujące elementy do 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>

Jak widać, użycie typu wirtualnego pozwoliło Ci zaoszczędzić pracę tworzenia Class5.

W celu uzyskania dalszych informacji sugeruję przeczytanie artykułu Alana Storma dotyczącego typów wirtualnych w Magento2 - http://alanstorm.com/magento_2_object_manager_virtual_types/

NoamN
źródło
1
dobre wyjaśnienie,
Anand Ontigeri
Łatwy do zrozumienia. Dziękujemy za udostępnienie tak podstawowego przykładu.
Kalyan Chakravarthi V
10

W tym samym di.xmlpliku znalazłem, że lessFileSourceBasejest przekazywany jako argument, lessFileSourceBaseFilteredktóry jest przekazywany jako argument, lessFileSourceBaseSortedktóry jest przekazywany jako argument typu Magento\Framework\Less\File\Collector\Aggregated.

Nie znalazłem żadnego innego wystąpienia lessFileSourceBase(lub lessFileSource) w innym pliku poza di.xmlmodułem głównym. Tylko w niektórych plikach pamięci podręcznej, ale nie są one ważne.

Sądzę, że jeśli nie zamierzasz używać typu wirtualnego w klasie PHP, ale tylko w diplikach xml, nie jest wymagane, aby wyglądał jak nazwa klasy i możesz użyć aliasu.

Ale to tylko spekulacje.
Będzie „zabawnie” spróbować stworzyć klasę i wprowadzić do jej konstruktora instancję, lessFileSourceBaseaby zobaczyć, jak się zachowuje.

Marius
źródło
1
przegapiłeś cytaty wokół słowa zabawa;)
David Manners
1
@DavidManners. Dobrze. Naprawiłem to. :)
Marius
@Marius: Jeśli zmienia \Magento\Framework\Session\Genericplik źródłowy do zależą Magento\Core\Model\Session\Storagezamiast StorageInterfacewas powinien dostać „klasa Magento \ Rdzeń \ Modele \ Session \ Storage nie istnieje” wyjątek. Powodem jest to, że ObjectManager nie tworzy instancji typu virtualType, a jedynie używa tego, aby określić, jakie argumenty podać konstruktorowi konkretnego typu, do którego odwołuje się definicja virtualType ( Magento\Framework\Session\Storagew powyższym przykładzie).
Chris O'Toole,
Widzi to w fabryce , gdzie $requestedTypereprezentuje typ wirtualny i służy do zbierania argumentów, ale $typejest konkretnym typem, na który virtualType odwzorowuje i jest używany do wywołania instancji obiektu.
Chris O'Toole,
Więc nawet jeśli lessFileSourceBasebyłby w stylu bardziej typu przestrzeni nazw \ klasy, nie pozwoliłby na bezpośrednie odwołanie przez inną klasę php, tylko do wstrzyknięcia przez di.xml
Chris O'Toole