DI plugins in Magento 2
In Magento 2, instead of the rewrite used in the first version, plug-ins appeared that allow you to override the behavior of most methods by intercepting the execution flow in three ways:
You can find out more about plugins in the documentation , and under the cut is just an example of use.
Suppose it is important for the end user that the accounting of the number of products is carried out with reference to a specific warehouse. Suppose a new table has been created in the database
Thus, in the admin panel, in the product grid, when outputing, you need to replace the data in the "Quantity" (
When analyzing the existing code, it turned out that the grid is built on the basis of the data provided
Here is the class code
That is, so that the method
We register the plugin in the DI configuration of our module (
For around-interception of the method,
After cleaning the generated files (
The class generated by Magento 2 is highlighted in orange (the 26th line is
From stektreysa seen that the DI in Magento 2 replaces the classes, which are defined plugins generated "interceptor", consistently applied
and sometimes the original methods themselves:
- before
- after
- around
You can find out more about plugins in the documentation , and under the cut is just an example of use.
Task
Suppose it is important for the end user that the accounting of the number of products is carried out with reference to a specific warehouse. Suppose a new table has been created in the database
warehouse
and the quantity of products in the warehouse is kept in a table warehouse_item
where the primary key is the combination of the warehouse identifier and the product identifier:CREATE TABLE warehouse_item (
product_id ...,
warehouse_id ...,
qty ...,
PRIMARY KEY (product_id, warehouse_id),
...
)
Thus, in the admin panel, in the product grid, when outputing, you need to replace the data in the "Quantity" (
cataloginventory_stock_item.qty
) column with their total value SUM(warehouse_item.qty)
. When analyzing the existing code, it turned out that the grid is built on the basis of the data provided
Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider
, and data on the quantity of the product is added to the provider through the DI ( magento/module-catalog-inventory/etc/adminhtml/di.xml
) settings :- Magento\CatalogInventory\Ui\DataProvider\Product\AddQuantityFieldToCollection
...
Here is the class code
AddQuantityFieldToCollection
:namespace Magento\CatalogInventory\Ui\DataProvider\Product;
...
class AddQuantityFieldToCollection implements AddFieldToCollectionInterface
{
public function addField(Collection $collection, $field, $alias = null)
{
$collection->joinField(
'qty',
'cataloginventory_stock_item',
'qty',
'product_id=entity_id',
'{{table}}.stock_id=1',
'left'
);
}
}
That is, so that the method
addField
does not work out and does not add the quantity of the product from the collection cataloginventory_stock_item
, you need to intercept its execution using the plugin using the method around
.Plugin creation
DI setup
We register the plugin in the DI configuration of our module (
etc/di.xml
or etc/adminhtml/di.xml
):
Plugin code
For around-interception of the method,
addField
create a method in the plugin aroundAddField
that " does nothing ":namespace Vendor\Module\Plugin;
use Magento\CatalogInventory\Ui\DataProvider\Product\AddQuantityFieldToCollection as Subject;
class AddQuantityFieldToCollection {
public function aroundAddField(Subject $subject, \Closure $proceed) {
return;
}
}
Generated class
After cleaning the generated files (
./var/generation/*
) and switching Admin WebUI to the products grid, the code of the newly created "interceptor" can be found in the file ./var/generation/Magento/CatalogInventory/Ui/DataProvider/Product/AddQuantityFieldToCollection/Interceptor.php
:___init();
}
/**
* {@inheritdoc}
*/
public function addField(\Magento\Framework\Data\Collection $collection, $field, $alias = null)
{
$pluginInfo = $this->pluginList->getNext($this->subjectType, 'addField');
if (!$pluginInfo) {
return parent::addField($collection, $field, $alias);
} else {
return $this->___callPlugins('addField', func_get_args(), $pluginInfo);
}
}
}
Stectrace Calls
The class generated by Magento 2 is highlighted in orange (the 26th line is
___callPlugins
after the else), white is our own plugin.Conclusion
From stektreysa seen that the DI in Magento 2 replaces the classes, which are defined plugins generated "interceptor", consistently applied
before
, after
, around
"wrapper" for the original methods:return $this->___callPlugins('addField', func_get_args(), $pluginInfo);
and sometimes the original methods themselves:
return parent::addField($collection, $field, $alias);