Virtual Types in Adobe Commerce

Virtual types in Adobe Commerce can seem intimidating at first, particular if your first exposure to them occurs when desperately trying to sort out the dependencies of a core component. Trying to make sense of these ephemeral non-classes when you’re just trying to track down an execution chain is not the best first impression! But virtual types are really just a natural application of the powers of dependency injection and nothing to be scared of.

You’re likely aware of the power of di.xml configuration to declare a specific implementation of a type globally:

… or in a particular context:

Virtual types are simply a way to “capture” a given set of implementations like in the latter example above, assigning a unique name to this “version” of the base class that can, in turn, be used in other DI configuration.

Let’s say you’ve built an order export management system with various “adapters” - one with logic for a flat file implementation, one using REST endpoints, etc. You have the interface MyVendor\MyOrderExport\Api\ExportAdapterInterface that all such adapters implement, and an “order manager” type used in various contexts that should inject the appropriate implementation. Virtual types can be used to declare the different “versions” of this manager class:

In the specific context where a particular manager is needed, simply typehint the “base” class (i.e., the one that really exists):

… and use the appropriate config in di.xml to inject your virtual type, ensuring you get an instance with its own appropriate dependencies injected:

The config saves you from a lot of fussy conditional code in your PHP itself, such as in a custom factory. With practice, virtual types can be used to powerful effect to improve your code’s separation of concerns and composition patterns.

Chris Nanninga

Director of Training and Development at SwiftOtter