10

I'm confused by Magento 2 documentation regarding plugins:

enter image description here

It is first said that:

Plugins cannot be used with virtual types

But then it is said that:

You can specify a class, interface, or virtual type as a type name which the plugin observes

Am I missing something or is the documentation contradicting itself ? Can we create plugins for virtual types ?

3
  • Could you, please, tell me whether you’ve found the right solution or not? You haven’t marked any of the replies as “correct”. Commented Jul 12, 2016 at 9:53
  • 1
    @SiarheyUchukhlebau yeah I tend to forget to mark answers as correct. Both answers are correct. Kandy is a Magento 2 developer so check his answer ;) Commented Jul 12, 2016 at 9:54
  • magento.stackexchange.com/questions/111577/… Is there any way to override this class using plugin.
    – Amit Singh
    Commented Jun 16, 2017 at 12:00

2 Answers 2

5

Plugins will work for virtual type but only if you specify it for parent classes or interfaces, but you cannot specify plugin specific for concrete virtual type

3
  • So we agree that the doc is not right as it says to explicitely specify the virtual type. Commented Jun 29, 2016 at 14:28
  • 3
    To be honest, plugins on virtual types worked before developer beta and we have bug to fix it.
    – KAndy
    Commented Jun 29, 2016 at 14:33
  • magento.stackexchange.com/questions/111577/… Is there any way to override this class using plugin.
    – Amit Singh
    Commented Jun 16, 2017 at 11:57
13

No, plugins on virtual types do not work.

Proof of concept code:

<?php

namespace Training\Example\Model

class Type
{
    public function bar()
    {
        return __CLASS__;
    }
}

Plugin using <type>:

<?php

namespace Training\Example\Model;

class TypePlugin
{
    public function afterBar(Type $subject)
    {
        return __CLASS__;
    }
}

Plugin using <virtualType>:

<?php

namespace Training\Example\Model;

class VirtualTypePlugin
{
    public function afterBar(Type $subject)
    {
        return __CLASS__;
    }
}

DI config:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <virtualType name="Foo" type="Training\Example\Model\Type">
        <plugin name="myfoo" type="Training\Example\Model\VirtualTypePlugin"/>
    </virtualType>
    <type name="Foo">
        <plugin name="yourfoo" type="Training\Example\Model\TypePlugin"/>
    </type>
</config>

Test:

    <?php

namespace Training\Example\Training\Integration;

use Magento\TestFramework\ObjectManager;
use Training\Example\Model\Type;
use Training\Example\Model\VirtualTypePlugin;

class VirtualTypePluginTest extends \PHPUnit_Framework_TestCase
{
    public function testPluginsOnVirtualTypesWork()
    {
        /** @var Type $instance */
        $instance = ObjectManager::getInstance()->create(Type::class);
        $this->assertSame(VirtualTypePlugin::class, $instance->bar());
    }
}

Result:

Failed asserting that two strings are identical.
Expected :Training\Example\Model\VirtualTypePlugin
Actual   :Training\Example\Model\Type
4
  • I would assume di.xml declaration tag would be type instead of virtualType according to the doc #totrustornottotrustthedoc Commented Jun 29, 2016 at 11:32
  • Updated the answer to include a type and virtualType plugin.
    – Vinai
    Commented Jun 29, 2016 at 14:12
  • magento.stackexchange.com/questions/111577/… Is there any way to override this class using plugin.
    – Amit Singh
    Commented Jun 16, 2017 at 12:00
  • You could intercept the concrete type the virtual type maps to, or alternatively overwrite the virtual type mapping to map to your own class, in effect giving you a kind of class override.
    – Vinai
    Commented Jun 17, 2017 at 12:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.