Hot answers tagged

67

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 ...


45

Plugins are omnipresent since it is possible to modify/replace the behavior of any public method in the system. Customizations should be done using plugins for public methods/classes marked with @api annotation (stable public API) whenever possible. Such approach guarantees that customization will stay functional after new Magento releases. In addition to ...


39

Plugins are sorted by sort order first, and then by method prefix. Example: for method with 3 plugins (PluginA, PluginB, PluginC) with following methods and sortOrder: PluginA (sortOrder = 10) beforeDispatch() afterDispatch() PluginB (sortOrder = 20) beforeDispatch() aroundDispatch() afterDispatch() PluginC (sortOrder = 30): beforeDispatch() ...


34

Interceptor classes are an implementation of the interceptor design pattern. The interceptors are how how Magento 2's object system implements a plugin system. As a client developer, the theory is you don't need to worry about interceptors -- you ask the object manager for an object of type X, and it returns it to you. The object you asked for may or may ...


29

You can disable plugin by name. In your case it authorization. <type name="Magento\Sales\Model\ResourceModel\Order\Plugin\Authorization"> <plugin name="authorization" disabled="true" /> <plugin name="vendor_name_authorization" type="Vendor\Name\Model\ResourceModel\Plugin\Sales\Order\...


28

In your di.xml you can do the following: <type name="\Magento\Catalog\Model\Product"> <plugin name="se_catalog_product_plugin_ample" disabled="true" /> </type> Magento does it out of the box in Magento/Backend/etc/adminhtml/di.xml with the following : <type name="Magento\Framework\App\Action\Action"> <plugin name="...


21

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\...


20

The obvious reason to use a rewrite instead of a plugin is when you need to override a private, protected or final methods. But also consider the following scenarios. 1st scenario (absolute sort order): Rewrites can be useful when you need your code to be run before plugins. I know you can do it by setting the plugin sortOrder, but you cannot be sure your ...


19

Is that even possible? Yes. How can I pluginize the magic getters/setters in magento 2? In the same way as a other public method. You need to declare plugin in di.xml configuration and add you custom code in plugin. public function before__call(\Magento\Review\Model\Review $review, $method, $args) { if ($method == 'setStatusId') { if (isset(...


16

From the Magento 2 cookbook: If there are multiple plugins that extend the same original function, they are executed in the following sequence: the before plugin with the lowest sortOrder the around plugin with the lowest sortOrder other before plugins (from the lowest to highest sortOrder) other around plugins (from the lowest to highest ...


14

If you use sergei.sss 1st solution, you will get the error of duplicate Magento\Sales\Model\ResourceModel\Order\Plugin\Authorization The correct way to do that is: <type name="Magento\Sales\Model\ResourceModel\Order\Plugin\Authorization"> <plugin name="authorization" disabled="true" /> <plugin name="vendor_name_authorization" type="...


14

Looks like you are using wrong class in your construct for $request. Change your construct to following and it should work: public function __construct( \Magento\Framework\Webapi\Rest\Request $request ) { $this->_request = $request; } After that you can get REST request's parameters in following way: var_dump($this->_request->getParams()...


13

Late answer but you need to change __constructor to __construct and it will work perfectly well. Don't use static ObjectManager if possible. You should always use DI instead.


13

You do this with using a requirejs mixin and the mage/utils/wrapper js module. Heres a demonstration of how the wrapper module functions: var wrapper = require('mage/utils/wrapper'); function multiply(a, b) { return a * b; } var wrapped1 = wrapper.wrap(multiply, function (_super) { var result = _super(); return result + 1; }); var wrapped2 = ...


12

Plugins only? Yes. You can write plugins for abstract classes and plugins should always be preferred over preferences if possible. Preferences are useful if you want to replace an implementation. I can't think of a use case to replace the implementation for all models that extend AbstractModel, if that's even logically possible. So what you probably want ...


12

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__; ...


11

Use plugins whenever possible, then observers (see the pros and cons of each), this will allow you to avoid conflicts with other extensions (3rd party modules). Preference should be used only if the whole core class/interface implementation should be substituted with custom one. Take into account that only one preference is active at any time (which one, is ...


11

We are working on "@api" annotations to annotate recommended methods that will be more stable across releases. If you worry about upgradability, in additional to what can have a plugin defined, you should also consider what should have a plugin defined. We don't recommend interception of non-@api methods, but sometimes we know that may be the best option. (...


11

You have an answer here : https://stackoverflow.com/a/29730810/4629261 The difference is, that a [Closure] must be an anonymous function, where [callable] also can be a normal function. You can see/test this with the example below and you will see that you will get an error for the first one: function callFunc1(Closure $closure) { $closure(); } ...


10

Every Class of an Magento Module is intercaptable. As described on the current wiki, it is limited by final methods and classes Not validated, but Classes of libraries (lib directory) are(/should) not allowed to get intercepted. The limitation how the object got created is not true anymore I think, at least if the autoloader is correctly configured. And ...


10

I think you misread the documentation. Basically the following are plugins limitations: Objects that are instantiated before Magento\Framework\Interception is bootstrapped Final methods Final classes Any class that contains at least one final public method Non-public methods Class methods (such as static methods) __construct Virtual types ...


9

For getting all available list of plugins: Go to vendor/magento/framework/Interception/PluginList/PluginList.php find method merge public function merge(array $config) { // default code echo "<pre>"; print_r($this->_data); die(); } For getting all available list of preferences: vendor/magento/framework/ObjectManager/Config/...


8

Full solution: include replaced classes before magento autoload them. So step by step: In file app/etc/NonComposerComponentRegistration.php add row $pathList[] = dirname(__DIR__) . '/etc/ClassReplacer.php'; In app/etc place file ClassReplacer.php with content class ClassReplacer { public function includeReplacedFiles($src) { try { ...


8

If abstract class have any public or protected method you want to override, there is a way actually if you can't use plugins. I had to override method _processDownload inside \Magento\Downloadable\Controller\Download, addings some 'if-s' inside. (If anyone has idea how can I add something like this inside method using plugins I will be gratful). Class is ...


8

Great question, I asked myself the same thing the other day and here's what I came up with: First, plugins cannot be used for final methods, final classes and classes created without dependency injection I reckon that's a very specific case but that's one case where you can't use plugins Second, you need to keep in mind the definition of a plugin. It is ...


8

Edit: just saw that you already tried the solution below. AFAIK it's the only "clean" way of doing it You can add the following in your own di.xml <config> <type name="{ObservedType}"> <plugin name="{pluginName}" disabled="true"/> </type> </config> Make sure your own module depends on the 3rd party module


8

You can do this by observer. SR/StackExchange/etc/frontend/events.xml <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> <event name="customer_register_success"> <observer name="sr_customer_account_createPost" instance="SR\...


8

If you look at target file Magento/Checkout/view/frontend/web/js/view/shipping.js,you'll see that this is requirejs module which returns UiComponent (child of Magento_Ui/js/form/form). In your example you have been used mage/utils/wrapper but this util applicable only for functions (like Magento/Checkout/view/frontend/web/js/action/create-billing-address.js)...


8

1) PHPStorm with XDebug: PHPStorm is my favorite IDE. It is an advanced IDE for PHP developers. Many developers still use only var_dump and die to debug the system. From my experience, these techniques are not powerful. They possibility will break the application. Magento 2 is a huge system. We should try with XDebug. With XDebug, we can see how the system ...


8

After so much investigation and implementation, I found a solution to display custom error message on checkout page. 1) Override a shipping.js file (vendor\magento\module-checkout\view\frontend\web\js\view\shipping.js) into your custom theme (app\design\frontend\Vendor\Theme\Module_Checkout\web\js\view\shipping.js): 2) Add your ajax call into ...


Only top voted, non community-wiki answers of a minimum length are eligible