51

I used both Plugin and Preference in Magento2 tutorial and both are working fine but what is the basic difference between them.

Code for plugin:

1.1) Add a plugin declaration into di.xml:

<type name="Magento\Catalog\Model\Product">
<plugin name="magento-catalog-product-plugin" type="Training\Test\Model\Product" sortOrder="10"/>
</type>

1.2) Create a plugin class:

<?php
namespace Training\Test\Model;
class Product {
public function afterGetPrice(\Magento\Catalog\Model\Product $product, $result) {
return 5;
}
}

Code for preference:

2.1) Create a preference declaration:

<preference for="Magento\Catalog\Model\Product"
type="Training\Test\Model\Testproduct" />

2.2) Create a new Product class:

<?php
namespace Training\Test\Model;
class Testproduct extends \Magento\Catalog\Model\Product
{
public function getPrice() {
return 3;
}
}

3 Answers 3

71

A preference is equivalent to class rewriting from Magento 1. It's equivalent to saying, "Whenever code asks for ClassA, give them MyClassB instead." MyClassB is expected to be a complete implementation of ClassA, plus whatever behavior you add or modify on top.

As in Magento 1, only one preference (rewrite) can be active for a class at one time unless you chain them manually (such that MyClassB extends OtherClassB, and OtherClassB extends ClassA).

A plugin allows you to execute code before, around, or after methods from the class you're hooking onto. Your plugin class does not replace the target class, and it is not an instance of it. You just have methods before{method}, around{method}, after{method} which get executed at the appropriate time in respect to {method} on the target class.

Since plugins do not replace the target class, any number of plugins can be active on a class simultaneously. Magento just executes them one after another based on the sortOrder parameter in your XML.

Because of that, plugins are much more flexible than preferences. You should use plugins whenever possible, and avoid preferences for rewriting classes unless absolutely necessary.

You can read more about how plugins work and how to use them in the official documentation.

2
  • Preference is not equivalent to class rewriting. It is way to provide default implementation for interfaces.
    – KAndy
    Commented Oct 5, 2015 at 17:02
  • 1
    @KAndy That may be the basic intended purpose, but a side effect of that is they also work for class overriding. Semantically they are the same. Class rewriting via preferences is what Yogesh was asking about, and also what the Fundamentals exercise he was working on instructs you to do.
    – Ryan Hoerr
    Commented Oct 5, 2015 at 20:41
24

In simple words

Preference is used for overriding class

Plugin is used for adding functionality before, after and around methods.

For As Your example:

<preference for="Magento\Catalog\Block\Product\ListProduct" type="Vendor\MyModule\Block\Product\ListProduct" /> 

Whenever code ask for ListProduct, preference said that

Hey, use Vendor\MyModule\Block\Product\ListProduct instead of Magento\Catalog\Block\Product\ListProduct

<type name="Magento\Catalog\Model\Product">
<plugin name="magento-catalog-product-plugin" type="Training\Test\Model\Product" sortOrder="10"/>
</type>

Whenever code ask for getPrice(), plugin said that

Hey use my getPrice() method before, after and around your getPrice() method

2
  • 2
    Good Explanation +1 for that Commented Dec 7, 2019 at 11:30
  • 1
    Nice one!!!!!!!!!! Commented Apr 12, 2021 at 11:50
4

In brief :

Preference is used to specify the default implementation of an interface.

Plugin ( Interceptor ) is used to extend the behavior of a public method of another class.

In detail :

Preference : If there is more than one class that implements an interface, then it is important to specify the default one of all the implemented classes. This is done through the preference node in the dependency injection file ( di.xml ).

Example :

<preference for="Magento\Catalog\Block\Product\ListProduct" type="Vendor\MyModule\Block\Product\ListProduct" /> 

This mapping is in app/etc/di.xml, so the object manager injects the Magento\Core\Model\Url implementation class wherever there is a request for the Magento\Core\Model\UrlInterface in the global scope.

Plugin(Interceptor) :

Say, a class A has method methodA which needs an extended functionality. Then, this is achieved through Plugins by creating class APlugin without modifying the original class A. Class APlugin has methods that runs before, after or around the required method.

Example :

<config>
    <type name="Magento\CatalogInventory\Model\Config\Backend\ShowOutOfStock">
        <plugin name="showOutOfStockValueChanged" type="Magento\Catalog\Model\Plugin\ShowOutOfStockConfig"/>
    </type>
</config>

This mapping is in app/etc/di.xml. One/Few of the class Magento\CatalogInventory\Model\Config\Backend\ShowOutOfStock method(s) are executed before/after/around the class Magento\Catalog\Model\Plugin\ShowOutOfStockConfig methods.

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.