Istanza di Magento 2 Helper


11

Quando penso di essermi preso la testa attorno al sistema DI di Magento 2 qualcosa viene fuori e lo scarterà.
Vedo nel codice principale diversi modi per accedere a un aiutante.
Ad esempio, Magento\Catalog\Controller\Category::_initCategoryc'è questo:

if (!$this->_objectManager->get('Magento\Catalog\Helper\Category')->canShow($category)) {
    return false;
}

Ma Magento\Catalog\Block\Category\Viewnell'aiutante viene iniettato nel costruttore

public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\Catalog\Model\Layer\Category $catalogLayer,
    \Magento\Framework\Registry $registry,
    \Magento\Catalog\Helper\Category $categoryHelper,
    array $data = array()
) {
    $this->_categoryHelper = $categoryHelper;
    $this->_catalogLayer = $catalogLayer;
    $this->_coreRegistry = $registry;
    parent::__construct($context, $data);
}

Questo mi ha portato a pensare che gli helper dovrebbero avere accesso in modo diverso nei controller e nei blocchi (e nei modelli), ma poi ho trovato un controller in cui un helper viene iniettato nel costruttore Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute.

Per favore cancella la nebbia per me.
Quando dovrei usare DI e quando dovrei usare objectManager? e perché?
Ho letto questa domanda: istanziare gli helper in Magento 2 . Questa è solo una domanda di follow-up su questo.

Risposte:


10

Preferirei DI dove possibile, poiché l'utilizzo del gestore degli oggetti è già una violazione della legge di Demeter. Quando si utilizza il gestore oggetti, queste dipendenze sono semplicemente nascoste nella logica del metodo.


Sì. Sono d'accordo. Userò DI, ma sono curioso di sapere perché questo è fatto nel core? Forse qualcuno non è ancora riuscito a riformattare le classi che ho citato?
Marius

Dopo tutto, stanno ancora rifattorizzando molto e sperano che tocchino anche questi posti. Ma anche non conoscere le priorità, che devono esistere se vogliono rilasciare effettivamente ad un certo punto. Quindi forse alcune nuove funzionalità o altre cattive pratiche verranno risolte per prime.
Tobias,

Cosa succede se si dispone di una classe di 10 funzioni e SOLO 1 funzione richiede un modello specifico? Non sarebbe ridondante (dal punto di vista delle prestazioni) caricare il modello attraverso l'iniezione del costruttore per ciascuna delle 10 funzioni mentre potremmo caricarlo usando il gestore degli oggetti solo all'interno di una singola funzione?
JohnyFree,

6

Non so molto dell'implementazione di Magento, ma sembra che ObjectManagersia un Service Locator .

Generalmente usare un Localizzatore di servizi per accedere alle dipendenze in un oggetto è piuttosto male, leggi questo articolo .

Definire esplicitamente le proprie dipendenze attraverso un costruttore è un approccio molto migliore. Aiuta a test di unità e problemi di runtime con servizi non definiti.

Iniettare il Gestore oggetti in una classe significa fondamentalmente iniettare un Registro nella tua classe che ha accesso a tutti i servizi delle tue applicazioni, il che ovviamente non è giusto.

Uso ZF2 abbastanza e generalmente definisco classi di piccole dimensioni per servizi, controller e qualsiasi classe che richieda dipendenze. Queste classi di fabbrica hanno accesso al Service Locator e prendono tutti i servizi da cui dipende l'oggetto e li iniettano attraverso il costruttore. L'uso di un Service Locator in una classe Factory va bene in quanto si tratta principalmente di buttare via il codice, qualcosa come questo, ad esempio.

Queste fabbriche sono ancora facili da testare .

IMO, Usa l'iniezione del costruttore dove possibile. Ancora una volta, non so troppo sull'implementazione di Magento e se ha il concetto di Fabbriche, da una rapida occhiata sembra che li supporti, ma definire esplicitamente le tue classi e usare un Service Locator per costruirle nelle classi Factory è un approccio molto più pulito.

Questo proviene da qualcuno che ha un'esposizione limitata agli schemi sopra menzionati, quindi vorrei anche sentire i pensieri / le esperienze degli altri in materia!

Più lettura


Grazie per la bella spiegazione. La mia domanda era "Perché ci sono 2 modi per accedere a un aiutante nel core?" quindi questo è un po 'fuori tema ma ha chiarito alcuni altri dubbi che avevo. :) Grazie.
Marius

Probabilmente direi che è solo qualcosa che non è ancora stato riformulato. O quello o potrebbe essere una cosa facile da usare. Richiedere ai consumatori di iniettare sempre tutte le loro dipendenze in un Controller potrebbe essere visto come controproducente, specialmente quando eseguono RAD. Dare ai consumatori entrambi i modi per accedere alle dipendenze consentirebbe l'approccio RAD, ma consentirebbe comunque ad altri di definire esplicitamente le loro dipendenze se lo desiderano.
Aydin Hassan,

5

Un altro modo di usare l'helper (nei template) è:

$this->helper('[Vendor]\[Module]\Helper\[Helper Name]')->getMethodName();

Spero sia utile se non lo sapessi già.


questo è in qualche modo simile all'utilizzo del gestore oggetti. Non sono sicuro che sia la migliore idea.
Marius

1
Il metodo sopra è solo per i modelli per quanto ne so. Il gestore oggetti viene utilizzato in controller, blocchi, modelli ecc.
rbncha,

1
Non si trova nello stesso campo di gioco del codice perché non ci sono dipendenze del codice dai modelli. I modelli sono solo consumatori e non inquinano alcun client con incapsulamento interrotto.
demonkoryu,

Non so cosa stia cercando di dire Demonkoryu. Ma il modo migliore per chiamare l'helper di qualsiasi modulo è questo. Questo è Magento. Come si suol dire, ogni codice di blocco / sezione deve essere richiamabile / modificabile senza toccare il nucleo. Quindi, tutto è correlato o ha dipendenze.
rbncha,

2

Sebbene sia una vecchia domanda, non sono sicuro che Marius abbia ottenuto la sua risposta. Credo che Marius possa rispondere meglio. Vorrei rispondere in breve. Perché Magento 2 suggerisce di usare DI invece di helper?

  • Rendere possibile / semplice l'isolamento nei test unitari
  • Definire esplicitamente le dipendenze di una classe
  • Facilitare una buona progettazione (ad esempio principio della responsabilità singola (SRP))
  • L'uso di DI nel modulo riduce il rischio di errori di incompatibilità quando Magento modifica l'implementazione sottostante di tali interfacce. Questo è un concetto importante da capire per gli sviluppatori di estensioni.

Perché il core M2 potrebbe non utilizzare DI in alcuni casi?

  • Numero decrescente di classi
  • Non creazione di interfacce non necessarie
  • Nessun rischio di bug di incompatibilità

Sebbene il modulo del catalogo Core sia stato utilizzato come supporto, ha ampiamente utilizzato DI. Nella mia ricerca, ho scoperto che Magento 2 utilizzava poche funzioni nei file di supporto del Catalogo principale che non sono adatte ai contratti di assistenza.

Se è necessario utilizzare esplicitamente una classe definita da Magento (come \ Magento \ Catalog \ Model \ Model), rendere esplicita la dipendenza implicita in base all'implementazione concreta anziché all'interfaccia del contratto di servizio.

Indubbiamente, lo sviluppatore di estensioni dovrebbe usare DI invece di Magento1 come Helper. Durante l'implementazione secondo le linee guida di Magento 2, il fallout è limitato. Quando si rompono le raccomandazioni, si verificano problemi.


Sì, ho avuto la mia risposta nel frattempo. Ma grazie per il tempo dedicato a rispondere. Queste sono informazioni preziose per le persone che cercano questo online.
Marius
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.