ความแตกต่างระหว่างประเภทและ 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

ขอบคุณ @Marius ฉันยังสงสัยว่าlessFileSourceBaseจะถูก จำกัด อยู่ที่ xml หรือว่าสามารถใช้ภายนอกได้ เดาฉันดีกว่าที่จะขุด
มารยาทของดาวิด

คำตอบ:


83

ประเภทเสมือนเป็นวิธีในการฉีดการพึ่งพาที่แตกต่างกันลงในคลาสที่มีอยู่โดยไม่กระทบกับคลาสอื่น

ตัวอย่างเช่นMagento\Framework\Session\Storageคลาสใช้$namespaceอาร์กิวเมนต์ในตัวสร้างซึ่งเป็นค่าเริ่มต้นเป็นค่า 'เริ่มต้น' และคุณสามารถใช้typeคำนิยามเพื่อเปลี่ยนเนมสเปซเป็น 'คอร์'

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

การกำหนดค่าด้านบนจะทำให้เป็นเช่นนั้นทุกอินสแตนซ์Magento\Framework\Session\Storageจะมีเนมสเปซของ 'คอร์' การใช้ชนิดเสมือนจะอนุญาตให้เทียบเท่ากับคลาสย่อยที่จะสร้างขึ้นซึ่งมีเพียงคลาสย่อยเท่านั้นที่มีค่าอาร์กิวเมนต์ที่เปลี่ยนแปลง

ใน codebase เราจะเห็นการกำหนดค่าสองแบบต่อไปนี้:

<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ที่ alters namespace Magento\Framework\Session\Genericและที่สองฉีดชนิดเสมือนเข้าไปใน สิ่งนี้อนุญาตให้Magento\Framework\Session\Genericปรับแต่งได้โดยไม่กระทบกับคลาสอื่น ๆ ที่ประกาศการพึ่งพาMagento\Framework\Session\Storage


ขอบคุณมาก @Chris ในที่สุดก็มีเหตุผลเชิงตรรกะฉันได้พบ
Suman-PHP4U

นั่นง่ายและเป็นการสาธิตที่ดีที่สุด
Umar

คำตอบนี้ดีกว่าเอกสารทางการของ Magento
Suman-PHP4U

<type>ใช้คลาสเสมือนซึ่งไม่มีอยู่จริง วิธีนี้การแก้ไขข้อโต้แย้งvirtualTypeจะมีผลเฉพาะเมื่อคลาสที่ใช้ virtualType ถูกเตรียมใช้งานซึ่งอยู่Magento\Framework\Session\Genericในตัวอย่าง
Arif Ahmad

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
การยกเครื่องที่ดี
Anand Ontigeri

เข้าใจง่าย ขอขอบคุณที่แบ่งปันตัวอย่างพื้นฐาน
Kalyan Chakravarthi V

10

ในเดียวกันdi.xmlไฟล์ฉันพบว่าlessFileSourceBaseจะถูกส่งเป็นอาร์กิวเมนต์สำหรับlessFileSourceBaseFilteredที่ถูกส่งผ่านเป็นอาร์กิวเมนต์สำหรับที่จะถูกส่งเป็นอาร์กิวเมนต์สำหรับการพิมพ์ lessFileSourceBaseSortedMagento\Framework\Less\File\Collector\Aggregated

ฉันพบว่าไม่มีการเกิดขึ้นของlessFileSourceBase(หรือlessFileSource) ในไฟล์อื่นยกเว้นdi.xmlจากโมดูลหลัก เฉพาะในไฟล์แคชบางตัวเท่านั้น แต่ไฟล์เหล่านั้นไม่สำคัญ

ฉันเดาว่าคุณจะไม่ใช้ประเภทเสมือนในคลาส PHP แต่เฉพาะในdiไฟล์ xml ดังนั้นคุณไม่จำเป็นต้องทำให้มันดูเหมือนชื่อคลาสและคุณสามารถใช้นามแฝงได้

แต่นี่เป็นเพียงการเก็งกำไรที่บริสุทธิ์
มันจะเป็น "ความสนุก" ที่พยายามสร้างคลาสและแทรกอินสแตนซ์ของคอนสตรัคเตอร์lessFileSourceBaseเพื่อดูว่ามันทำงานอย่างไร


1
คุณพลาดคำพูดรอบคำสนุก;)
David Manners

1
@DavidManners ขวา. ฉันซ่อมมัน. :)
Marius

@Marius: ถ้าคุณเปลี่ยนแปลง\Magento\Framework\Session\Genericแฟ้มแหล่งที่มาขึ้นอยู่กับMagento\Core\Model\Session\StorageแทนของStorageInterfaceคุณควรจะได้รับ 'Class วีโอไอพี \ หลัก \ รุ่น \ \ Session จัดเก็บไม่อยู่' ข้อยกเว้น เหตุผลที่ว่า ObjectManager ไม่ได้สร้างอินสแตนซ์ของ virtualType แต่เพียงใช้เพื่อกำหนดว่าอาร์กิวเมนต์ใดที่จะจัดเตรียมสำหรับตัวสร้างประเภทคอนกรีตที่ถูกอ้างถึงโดยนิยาม virtualType ( Magento\Framework\Session\Storageสำหรับตัวอย่างด้านบน)
Chris O'Toole

สามารถเห็นสิ่งนี้ได้ในโรงงานซึ่ง$requestedTypeแสดงถึงประเภทเสมือนจริงและใช้เพื่อรวบรวมอาร์กิวเมนต์ แต่$typeเป็นประเภทคอนกรีตที่ virtualType จับคู่กับและใช้สำหรับการเรียกการสร้างอินสแตนซ์ของวัตถุ
Chris O'Toole

ดังนั้นแม้ว่าจะlessFileSourceBaseอยู่ในรูปแบบประเภท namespace \ class มากขึ้นก็จะไม่อนุญาตให้มีการอ้างอิงโดยตรงจากคลาส php อื่นเพียงเพื่อการฉีดผ่าน di.xml
Chris O'Toole
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.