Dependency injection: come funzionano le preference in Magento 2

Una delle novità introdotte in Magento 2, è l’utilizzo del pattern dependency injection. Questo in realtà meriterebbe un articolo a sè stante, ma almeno per il momento, diciamo che ha l’obiettivo di migliorare la gestione delle dipendenze, evitando di inserire riferimenti a classi esterne direttamente all’interno di un metodo, come invece avviene qui

public function getSku($id)
{
    $db  = new DBHandler;
    $row = $db->query('SELECT sku FROM products WHERE id = ?',$id);
    return $row['sku'];
}

e quindi passare le dipendenze tramite costruttore oppure come parametri del metodo, favorendo così il riutilizzo e la testabilità.

Una delle modalità per l’estensione di magento 2 basate sul dependency injection è la cosiddetta preference. In breve questa consiste nel poter scegliere quale classe assegnare, ogni volta che l’object manager tenta di istanziare un oggetto. Detto così potrebbe sembrare poco chiaro il meccanismo.

Per chiarire, facciamo un esempio tramite un modulo. Iniziamo con il registration.php nella cartella app/code/Mageunbox/Preference

<?php
use \Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Mageunbox_PreferenceExample',
    __DIR__
);

e creiamo anche il file module.xml nella cartella etc

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Mageunbox_PreferenceExample" setup_version="1.0.0">
        <sequence></sequence>
    </module>
</config>

e proseguiamo con la definizione della preference, creando il file di.xml

<?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\Pricing\PriceCurrencyInterface" 
      type="Mageunbox\PreferenceExample\Model\PriceCurrency" />
</config>

In questo modo quindi, ogni volta che nel codice compare il typehint PriceCurrencyInterface, verrà creata un’istanza della classe che andremo ad aggiungere nel nostro modulo, definita nell’attributo type. Nel nostro caso estendiamo la classe Magento\Directory\Model\PriceCurrency, per ridefinire soltanto il metodo round() in modo tale da cambiare le cifre decimali utilizzate per l’arrotondamento. Il codice del file PriceCurrency.php sarà il seguente

<?php
namespace Mageunbox\PreferenceExample\Model;
class PriceCurrency extends \Magento\Directory\Model\PriceCurrency
{
    public function round($price)
    {
        return round($price, 1);
    }
}

E installiamo il modulo attraverso il comando

bin/magento setup:upgrade

A questo punto, se voleste verificare il funzionamento del modulo, basta aggiungere al carrello un prodotto con un prezzo ad esempio di 10,49€ che dopo l’aggiunta diventerà 10,50€.

In conclusione, le preference si possono paragonare alla funzionalità di rewrite delle classi di Magento 1. In presenza di più moduli che fanno riferimento alla stessa interfaccia, solo una classe verrà effettivamente utilizzata e sarà quella definita nel modulo caricato per ultimo.

Lascia un commento