Magento 2 has a lot going on under the hood. Sometimes, you need to tweak how a class behaves without rewriting everything. That’s exactly where Virtual Types step in.
In this post, we’ll break down:
- What Virtual Types are
- Why they exist
- How to use them with a simple example
What is a Virtual Type?
A Virtual Type in Magento 2 is not a real PHP class.
Instead, it’s a way to configure an existing class differently, without actually creating a new class file.
Think of it like this:
- You have one class, say
Book. - In some cases, you want a
ScienceBookwith slightly different behavior. - In other cases, you want a
HistoryBook.
Instead of creating two new PHP classes (ScienceBook.php and HistoryBook.php), you can define virtual types in Magento’s DI configuration.
Why Do We Need Virtual Types?
Here are the key reasons:
- Reusability
You can reuse the same class logic but inject different dependencies or arguments. - No Extra Classes Needed
You avoid cluttering your codebase with multiple “almost similar” classes. - Clean Configuration
You keep your variations inside XML configuration, rather than duplicating code.
In short, virtual types give you flexibility without extra PHP files.
How to Use Virtual Types
Let’s go step by step with an example.
1. A Base Class
Suppose we have a class Book.php:
<?php
namespace Ecommet\HelloWorld\Model;
class Book
{
protected $category;
public function __construct($category = 'General')
{
$this->category = $category;
}
public function getCategory()
{
return $this->category;
}
}By default, this book has the category General.
2. Define Virtual Types in di.xml
Now, let’s say we want two variations: ScienceBook and HistoryBook.
We don’t create new PHP files. Instead, we define them in etc/di.xml:
<virtualType name="ScienceBook" type="Ecommet\HelloWorld\Model\Book">
<arguments>
<argument name="category" xsi:type="string">Science</argument>
</arguments>
</virtualType>
<virtualType name="HistoryBook" type="Ecommet\HelloWorld\Model\Book">
<arguments>
<argument name="category" xsi:type="string">History</argument>
</arguments>
</virtualType>Here’s what’s happening:
ScienceBookandHistoryBookare virtual types.- Both use the same underlying class
Vendor\Module\Model\Book. - The only difference is the argument we pass (
ScienceorHistory).
3. Use Virtual Types
Now, if we inject ScienceBook or HistoryBook anywhere in our code, Magento will create them for us:
public function __construct(
\ScienceBook $scienceBook,
\HistoryBook $historyBook
) {
echo $scienceBook->getCategory(); // Science
echo $historyBook->getCategory(); // History
}And notice—we didn’t create extra PHP files for these classes.
When Should You Use Virtual Types?
- When you need different configurations of the same class.
- When you want to avoid duplicate classes.
- When you’re building flexible and reusable modules.
They are especially useful in complex Magento modules where the same service might need to behave slightly differently based on the context.
Once you get comfortable with this concept, you’ll find Virtual Types extremely handy in real-world Magento development.



