Apa perbedaan antara tipe dan tipe virtual

41

Dalam di.xmlyang dilengkapi dengan Magento2 ada simpul typedan simpul virtualType. Pertanyaan saya adalah apa ini virtualTypedan dalam hal apa seharusnya itu digunakan type?

Di beberapa tempat sepertinya tautan simbolis atau menulis ulang:

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

Di mana satu path lengkap diubah menjadi yang lain tetapi di tempat lain tampaknya digunakan sebagai cara untuk mendefinisikan alias lebih pendek.

<virtualType name="lessFileSourceBase" type="Magento\Framework\View\File\Collector\Base">
David Manners
sumber
3
Saya tidak tahu (belum) bahkan apa yang mereka maksud tetapi Anda dapat mulai menggali dari sini: Magento\Framework\ObjectManager\Config\Mapper\Dom::convert. Ada switchpernyataan di sana di suatu tempat.
Marius
Terima kasih @Marius, saya juga bertanya-tanya apakah lessFileSourceBaseterbatas pada xml atau apakah itu juga dapat digunakan di luar. Kira saya lebih baik menggali.
David Manners

Jawaban:

84

Tipe virtual adalah cara untuk menyuntikkan dependensi yang berbeda ke dalam kelas yang ada tanpa mempengaruhi kelas lain.

Sebagai contoh, Magento\Framework\Session\Storagekelas mengambil $namespaceargumen dalam konstruktornya, yang default ke nilai 'default', dan Anda bisa menggunakan typedefinisi untuk mengubah namespace menjadi 'core'.

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

Konfigurasi di atas akan membuatnya sehingga semua instance Magento\Framework\Session\Storagememiliki namespace 'core'. Menggunakan tipe virtual memungkinkan untuk setara dengan sub-kelas yang akan dibuat, di mana hanya sub-kelas yang memiliki nilai argumen yang diubah.

Dalam basis kode kita melihat dua konfigurasi berikut:

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

Cuplikan pertama membuat tipe virtual Magento\Core\Model\Session\Storageyang mengubah namespace, dan yang kedua menyuntikkan tipe virtual Magento\Framework\Session\Generic. Ini memungkinkan Magento\Framework\Session\Genericuntuk dikustomisasi tanpa mempengaruhi kelas-kelas lain yang juga menyatakan ketergantunganMagento\Framework\Session\Storage

Chris O'Toole
sumber
Terima kasih banyak @ Chris akhirnya beberapa pembenaran logis saya temukan
Suman-PHP4U
Itu adalah demonstrasi sederhana dan terbaik.
Umar
Jawaban ini lebih baik daripada dokumen resmi Magento
Suman-PHP4U
<type>menggunakan kelas virtual yang sebenarnya tidak ada. Dengan cara ini argumen modifikasi dalam virtualTypeakan berlaku hanya ketika kelas menggunakan virtualType diinisialisasi yang ada Magento\Framework\Session\Genericdalam contoh
Arif Ahmad
21

Cara lain untuk memahami tipe virtual -

Katakanlah Anda memiliki kelas \Class1, yang memiliki konstruktor berikut -

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

Dan \Class2memiliki konstruktor berikut -

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

Sekarang, Anda ingin mengubah jenis $argOfClass2dari \Class3menjadi \Class4, tetapi hanya ketika \Class2digunakan sebagai $argOfClass1.

Cara "lama" untuk melakukannya adalah dengan menambahkan yang berikut di di.xml-

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

dimana \Class5yang berikut ini:

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

Alih-alih menggunakan cara ini, Anda bisa menggunakan tipe virtual untuk mencapai hal yang sama, dengan menambahkan yang berikut ke 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>

Seperti yang Anda lihat, menggunakan tipe virtual menyelamatkan Anda karya penciptaan Class5.

Untuk referensi lebih lanjut saya sarankan untuk membaca artikel Alan Storm mengenai tipe virtual di Magento2 - http://alanstorm.com/magento_2_object_manager_virtual_types/

NoamN
sumber
1
expalination yang baik,
Anand Ontigeri
Mudah dimengerti. Terima kasih telah berbagi contoh dasar seperti itu.
Kalyan Chakravarthi V
10

Dalam di.xmlfile yang sama saya menemukan yang lessFileSourceBasedilewatkan sebagai argumen untuk lessFileSourceBaseFilteredyang dilewatkan sebagai argumen untuk lessFileSourceBaseSortedyang dilewatkan sebagai argumen untuk tipe Magento\Framework\Less\File\Collector\Aggregated.

Saya tidak menemukan kejadian lain lessFileSourceBase(atau lessFileSource) di file lain kecuali di.xmldari modul inti. Hanya di beberapa file cache tetapi itu tidak penting.

Saya kira jika Anda tidak akan menggunakan tipe virtual dalam kelas PHP, tetapi hanya dalam difile xml maka Anda tidak diharuskan untuk membuatnya terlihat seperti nama kelas dan Anda dapat menggunakan alias.

Tapi ini hanya spekulasi murni.
Akan "menyenangkan" untuk mencoba membuat kelas dan menyuntikkan konstruktor sebagai contoh lessFileSourceBaseuntuk melihat bagaimana perilakunya.

Marius
sumber
1
Anda melewatkan tanda kutip di sekitar kata fun;)
David Manners
1
@ Davidvider. Kanan. Aku telah memperbaikinya. :)
Marius
@Marius: Jika Anda mengubah \Magento\Framework\Session\Genericbergantung pada file sumber Magento\Core\Model\Session\Storagealih-alih, StorageInterfaceAnda harus mendapatkan pengecualian 'Kelas Magento \ Core \ Model \ Session \ Storage tidak ada'. Alasannya adalah bahwa ObjectManager tidak membuat turunan dari virtualType, tetapi hanya menggunakannya untuk menentukan argumen apa yang disediakan untuk konstruktor dari tipe konkret yang dirujuk oleh definisi virtualType ( Magento\Framework\Session\Storageuntuk contoh di atas).
Chris O'Toole
Dapat melihat ini di Factory , di mana $requestedTypemewakili tipe virtual dan digunakan untuk mengumpulkan argumen, tetapi $typeadalah tipe konkret yang dipetakan oleh virtualType dan digunakan untuk panggilan instanceasi objek.
Chris O'Toole
Jadi, bahkan jika lessFileSourceBaseberada dalam gaya tipe namespace \ kelas yang lebih, itu tidak akan memungkinkan untuk referensi langsung oleh kelas php lain, hanya untuk injeksi melalui di.xml
Chris O'Toole