Preferences in Magento 2 are just like how rewrites are in Magento 1. They basically let you substitute one instance of a class for another, in the Magento 2. This is an extremely powerful feature, but also comes along with the same responsibility as of Magento 1. Basically, No two modules can rewrite the same class. If two modules attempt to do so, there will be a conflict.
Create A Sandbox Script
Create a simple sandbox script by creating a demo.php file on Magento 2 root, enter the following:
<?php
require_once 'app/bootstrap.php';
$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
$sample = $bootstrap->getObjectManager()->create('\Psr\Log\LoggerInterface');
\Zend_Debug::dump(get_class($sample));
Now, go to http://www.xyz.com/demo.php. On the screen, you should see the following:
string 'Magento\Framework\Logger\Monolog' (length=32)
Now, even though you specified \Psr\Log\LoggerInterface, you were given an instance of Magento\Framework\Logger\Monolog. Why? That’s because Magento 2 specified a preference for which class is to be used whenever the LoggerInterface class is requested. That definition is located in app/etc/di.xml.
Create a Preference
In your module, Ex:Companyname_Packagename, Create a di.xml file on the <root>/app/code/Companyname/Packagename/etc folder.
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Framework\Logger\Monolog" type="Companyname\Packagename\Model\Log"/>
</config>
Now, let’s create a class.
Inside of app/code/Companyname/Packagename/Model/Log.php, enter the following:
<?php
namespace Companyname\Packagename\Model;
use \Magento\Framework\Logger\Monolog;
class Log extends Monolog {
}
Now, go to http://www.xyz.com/demo.php. On the screen, you should see the following:
string 'Companyname\Packagename\Model\Log' (length=36)
When we specified the \Psr\Log\LoggerInterface:
- Magento 2 prompted the object manager that there was a preference for that class.
- That was Magento\Framework\Logger\Monolog originally.
- The object manager took that preference and then started all over again.
- When it attempted to use the Monolog class, the object manager once again declared that there was another preference for the Monolog class.
- This time it was for our own class, i.e. Companyname\Packagename\Model\Log
Basically, whenever the LoggerInterface class is requested, our newly created class will be used instead!
Recommended: preference
should be the last option if it is not possible to make use of the plugin
to rewrite the method of the class.
Thank you for reading. Your feedback is welcome in the comments section, and we’re available to assist with any Magento store development or customizations you may need