Skip to content
intermediate Phase 28 · DI Advanced

Virtual Types - Advanced DI

Understanding Magento 2 virtual types: creating anonymous class configurations, aliasing, use cases for testing and customization

45m
0 problems
Topic Progress 0%

Virtual Type Fundamentals

What is a Virtual Type?

A virtual type creates an anonymous class configuration without defining a new PHP class. It's a DI alias with custom arguments.

<virtualType name="ActiveWarrantyRepository" type="Amazon\Prep\Model\WarrantyRepository">
    <arguments>
        <argument name="statusFilter" xsi:type="string">active</argument>
    </arguments>
</virtualType>

How Virtual Types Work

1. Virtual type is registered as a named configuration
2. When injected, ObjectManager creates the type class
3. Arguments are applied from the virtual type config
4. Instance is created (shared or non-shared based on config)

Basic Virtual Type

<!-- Define virtual type -->
<virtualType name="PremiumWarranty" type="Amazon\Prep\Model\Warranty">
    <arguments>
        <argument name="type" xsi:type="string">premium</argument>
        <argument name="duration" xsi:type="number">36</argument>
    </arguments>
</virtualType>

<!-- Use virtual type in other configuration -->
<type name="Amazon\Prep\Service\WarrantyService">
    <arguments>
        <argument name="defaultWarranty" xsi:type="object">PremiumWarranty</argument>
    </arguments>
</type>

Virtual Type vs Preference

Aspect Virtual Type Preference
Purpose Create named configuration Replace interface implementation
New class No (uses existing) No (maps to existing)
Customization Arguments only Full replacement
Conflict Low High
Use case Configuration aliasing Interface replacement

Virtual Type Configuration

Virtual Type with Arguments

<virtualType name="CachedProductRepository" type="Magento\Catalog\Model\ProductRepository">
    <arguments>
        <argument name="cache" xsi:type="object">Magento\Framework\Cache\Frontend\Interface</argument>
        <argument name="cacheLifetime" xsi:type="number">3600</argument>
        <argument name="cacheTags" xsi:type="array">
            <item name="0" xsi:type="string">catalog_product</item>
        </argument>
    </arguments>
</virtualType>

Virtual Type with Shared Flag

<!-- Non-shared virtual type -->
<virtualType name="TransientWarranty" type="Amazon\Prep\Model\Warranty" shared="false"/>

<!-- Shared virtual type (default) -->
<virtualType name="SingletonWarranty" type="Amazon\Prep\Model\Warranty"/>

Virtual Type for Collections

<virtualType name="ActiveWarrantyCollection" type="Amazon\Prep\Model\ResourceModel\Warranty\Collection">
    <arguments>
        <argument name="mainTable" xsi:type="string">vendor_warranty</argument>
        <argument name="idFieldName" xsi:type="string">warranty_id</argument>
    </arguments>
</virtualType>

<!-- Use in repository -->
<type name="Amazon\Prep\Model\WarrantyRepository">
    <arguments>
        <argument name="collectionFactory" xsi:type="object">ActiveWarrantyCollection</argument>
    </arguments>
</type>

Virtual Type for Helpers

<virtualType name="StoreConfigHelper" type="Amazon\Prep\Helper\Config">
    <arguments>
        <argument name="configPath" xsi:type="string">vendor_prep/general</argument>
        <argument name="scope" xsi:type="string">store</argument>
    </arguments>
</virtualType>

Virtual Type Use Cases

Use Case 1: Different Configurations for Same Class

<!-- Standard warranty -->
<virtualType name="StandardWarranty" type="Amazon\Prep\Model\Warranty">
    <arguments>
        <argument name="duration" xsi:type="number">12</argument>
        <argument name="price" xsi:type="number">49.99</argument>
    </arguments>
</virtualType>

<!-- Premium warranty -->
<virtualType name="PremiumWarranty" type="Amazon\Prep\Model\Warranty">
    <arguments>
        <argument name="duration" xsi:type="number">36</argument>
        <argument name="price" xsi:type="number">149.99</argument>
    </arguments>
</virtualType>

<!-- Use in services -->
<type name="Amazon\Prep\Service\WarrantyService">
    <arguments>
        <argument name="standardWarranty" xsi:type="object">StandardWarranty</argument>
        <argument name="premiumWarranty" xsi:type="object">PremiumWarranty</argument>
    </arguments>
</type>

Use Case 2: Testing

<!-- etc/di.xml (test area) -->
<virtualType name="MockWarrantyRepository" type="Amazon\Prep\Model\Mock\MockWarrantyRepository">
    <arguments>
        <argument name="testData" xsi:type="array">
            <item name="0" xsi:type="array">
                <item name="id" xsi:type="number">1</item>
                <item name="name" xsi:type="string">Test Warranty</item>
            </item>
        </argument>
    </arguments>
</virtualType>

<type name="Amazon\Prep\Service\WarrantyService">
    <arguments>
        <argument name="repository" xsi:type="object">MockWarrantyRepository</argument>
    </arguments>
</type>

Use Case 3: Environment-Specific

<!-- etc/di.xml (global) -->
<virtualType name="DatabaseLogger" type="Amazon\Prep\Logger\Database">
    <arguments>
        <argument name="table" xsi:type="string">logs</argument>
    </arguments>
</virtualType>

<!-- etc/frontend/di.xml -->
<virtualType name="FileLogger" type="Amazon\Prep\Logger\File">
    <arguments>
        <argument name="path" xsi:type="string">var/log/frontend.log</argument>
    </arguments>
</virtualType>

Virtual Type Best Practices

Naming Conventions

<!-- Use descriptive names -->
<virtualType name="ActiveWarrantyRepository" .../>  <!-- Good -->
<virtualType name="VType1" .../>  <!-- Bad -->

<!-- Prefix with module name -->
<virtualType name="AmazonPrepActiveWarranty" .../>  <!-- Good -->
<virtualType name="ActiveWarranty" .../>  <!-- Okay if unique -->

When to Use Virtual Types

✅ Use when:

  • Different configurations for same class
  • Creating named aliases for clarity
  • Testing with mock implementations
  • Environment-specific configurations
  • Avoiding preference conflicts

❌ Don't use when:

  • You need to replace entire class (use preference)
  • You need to extend behavior (use plugin)
  • Simple argument override (use type arguments directly)

Debugging Virtual Types

# Check generated code
cat var/di/development.log | grep -A10 "ActiveWarrantyRepository"

# Verify virtual type resolution
bin/magento setup:di:compile

# Check for errors
bin/magento dev:di:log

Virtual Type + Plugin Combo

<!-- Virtual type for configuration -->
<virtualType name="ConfiguredService" type="Amazon\Prep\Service\WarrantyService">
    <arguments>
        <argument name="apiKey" xsi:type="string">sk_test_abc</argument>
    </arguments>
</virtualType>

<!-- Plugin extends the virtual type -->
<type name="Amazon\Prep\Service\WarrantyService">
    <plugin name="service_logging" type="Amazon\Prep\Plugin\ServicePlugin"/>
</type>

Quiz

1. What is a virtual type in Magento DI?

Question 1 options

2. When should you use a virtual type instead of a preference?

Question 2 options

3. How do you use a virtual type in other configurations?

Question 3 options

Flashcards

Question

What does a virtual type create?

Answer

An anonymous class configuration with custom arguments

Question

How do you reference a virtual type?

Answer

xsi:type="object" with the virtual type name

Question

Virtual type vs preference: which replaces entire class?

Answer

Preference replaces entire class; virtual type configures existing class

Question

When are virtual types useful for testing?

Answer

When you need mock implementations with test data

Question

Can virtual types be non-shared?

Answer

Yes, set shared="false" on the virtualType element

Revision Notes

Key Takeaways

  • 1. Virtual types create named configurations for existing classes
  • 2. Use xsi:type="object" to reference virtual types
  • 3. Virtual types are for configuration; preferences are for replacement
  • 4. Virtual types are useful for testing and environment-specific configs
  • 5. Always use descriptive naming conventions for virtual types

Interview Tips

  • Explain virtual types vs preferences vs plugins
  • Know when to use virtual types for testing
  • Be ready to create virtual type configurations
  • Discuss virtual type naming best practices

Cheat Sheet

Virtual type:
  <virtualType name="Alias" type="RealClass">
    <arguments>
      <argument name="key" xsi:type="string">value</argument>
    </arguments>
  </virtualType>

Reference:
  <argument name="dep" xsi:type="object">Alias</argument>

Use cases: config aliasing, testing, environment-specific