Iniezione di dipendenze in un modello CRUD / Abstract di Magento 2


12

È possibile iniettare una dipendenza in un modello CRUD Magento 2?

Questo è - Magento 2 ha una base di classe del modello astratto: Magento\Framework\Model\AbstractModel. Se si desidera creare un semplice oggetto modello Crea, Leggi, Aggiorna, Elimina, si estende questa classe con la propria classe.

class Foo extends Magento\Framework\Model\AbstractModel
{
}

È possibile avere delle dipendenze iniettate nel __constructmetodo del modello ? Quando provo, finisco per ricevere il seguente errore.

Errore irreversibile: impossibile creare un'istanza della classe astratta Magento \ Framework \ Model \ ResourceModel \ AbstractResource

Il colpevole sembra essere il AbstractModel's __constructmetodo.

public function __construct(
    \Magento\Framework\Model\Context $context,
    \Magento\Framework\Registry $registry,
    \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
    \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
    array $data = []
) {

Esistono due suggerimenti per il tipo in questo costruttore ( Magento\Framework\Model\ResourceModel\AbstractResource, Magento\Framework\Data\Collection\AbstractDb) che non sono interfacce di gestione oggetti Magento. Sono lezioni astratte. Quando estendo questa classe e provo ad aggiungere la mia dipendenza iniettata

class Foo extends Magento\Framework\Model\AbstractModel
{
    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        array $data = [],
        \Package\Module\Model\Mine $mine,

    ) {
        //...
        parent::__construct($context, $registry, $resource, $resourceCollection, $data);

    }
}

Magento viene rilasciato quando il gestore oggetti tenta di creare un'istanza delle classi astratte.

Posso "risolvere" questo spostando la mia dipendenza dagli oggetti di fronte alle classi astratte

    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,

        \Package\Module\Model\Mine $mine,

        \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        array $data = [],
    ) {  

Tuttavia, questo ha cambiato l'ordine degli argomenti. In una classe completamente gestita da oggetti, questo non sarebbe un problema. Tuttavia, il fatto che esistano questi suggerimenti di tipo di classe astratta implica che ci sono parti del sistema Magento che istanzeranno manualmente (cioè non tramite il gestore oggetti o DI) un'istanza di oggetti CRUD e passeranno oggetti conformi ai suggerimenti di tipo in quell'ordine specifico .

È sicuro? vale a dire queste classi astratte nel costruttore di un modello astratto sono solo codice legacy e non vengono utilizzate? O parti del sistema useranno ancora queste, il che significa che non è possibile iniettare dipendenze in un modello CRUD?

Risposte:


9

Innanzitutto il costruttore è api privato di classe. La funzione di costruzione ha un significato speciale e non richiede di avere lo stesso elenco / ordine di argomenti della classe genitore.

È possibile iniettare una dipendenza in un modello CRUD Magento 2?

Sì, naturalmente.

È sicuro?

Sì, ma Magento Object Manager presume che tutti i parametri opzionali siano posizionati alla fine dell'elenco e che i parametri richiesti dopo facoltativo non vengano risolti.

Gli argomenti $ resource, $ resourceCollection sono legacy ma sono ancora ampiamente utilizzati nelle classi Model. La maggior parte del modello utilizza codice come questo per inizializzare la risorsa e la classe di raccolta.

protected function _construct() { 
    $this->_init('Magento\AdminNotification\Model\Resource Model\Inbox'); 
}

Questo è il motivo per cui questo parametro è facoltativo. Ma, ad esempio, nel test unitario passiamo la beffa di risorse o raccolte nel costruttore per consentire la sostituzione della realizzazione.


@Kanday Il dipartimento di ingegneria / architettura di Magento ha mai fatto una dichiarazione pubblica secondo cui l'ordine dei costruttori per le classi principali è irrilevante? O è solo la speranza della maggior parte delle persone che ci lavorano?
Alan Storm,

Non lo chiamerò "irrilevante". Solo OM passerà gli argomenti richiesti al costruttore e non dipende dall'ordine nella classe genitore. Inoltre, IN usa i nomi dei parametri, quindi ora è meglio non cambiarli (è diverso dal linguaggio php, dove puoi cambiare i nomi dei parametri come vuoi)
KAndy

Non sono sicuro di capire quello che stai dicendo. Stai dicendo che, ad un certo punto in futuro, il codice principale del sistema Magento potrebbe ricominciare a considerare l'argomento / ordine dei parametri di nuovo significativo?
Alan Storm,

Credo che no
KAndy il

grazie ancora! FWIW, e per i Googler, sembra che dovrebbe essere una cosa sicura da fare. Da quello che posso dire non esiste un codice di sistema Magento che istanzia automaticamente alla cieca un modello assumendo l'ordine dei parametri del costruttore.
Alan Storm,

6

Questo sembra essere sicuro. Almeno, Magento lo sta facendo in diversi punti. Vedere i metodi __construct nel seguente elenco (non esclusivo) di classi per esempi

  • \ Magento \ Tema \ modello \ a tema \ File
  • \ Magento \ Tema \ modello \ design
  • \ Magento \ vendite \ modello \ Order \ di accredito

Sfortunatamente, non posso rispondere all'altra parte della tua domanda.


4
  1. Come usi il tuo modello?
  2. Nel tuo caso $mineè una richiesta di parametro, mentre $resource, $resourceCollectione $datasono facoltativi . I parametri opzionali dovrebbero sempre andare per ultimi, altrimenti è impossibile lavorare con loro come con facoltativo. Quindi mi sembra OK che dovresti specificare $mineprima di qualsiasi parametro facoltativo.

Tranne che i parametri astratti non sono parametri iniettati di dipendenza e se il codice di sistema di base di Magento si aspetta che si trovino lì spostandosi $minein primo piano nella coda creerà errori. Se il codice di sistema di base Magento non li utilizza, perché sono presenti? Questa è la domanda che sto cercando di raggiungere in fondo. Solo perché sono in grado di utilizzare il mio modello con il parametro spostato non lo rende sicuro.
Alan Storm,

Alcuni modelli possono comunque utilizzare questi parametri opzionali per passare un modello di risorsa personalizzato. Ad esempio, github.com/magento/magento2/blob/develop/app/code/Magento/…
BuskaMuza,

Magento usa la riflessione per determinare se il parametro è facoltativo o meno. E PHP considera tutti i parametri in piedi prima del parametro richiesto come richiesto . Quindi, se ti sposti $mineprima dei parametri opzionali, diventano davvero opzionali e Magento passa solo i valori predefiniti ( null, array()). Se inserisci un parametro richiesto dopo quelli opzionali, PHP considera parametri opzionali come quelli obbligatori e Magento ha provato a crearne un'istanza (ma non ci sono preferenze).
BuskaMuza,

Anche se concordo sul fatto che sembra confuso e forse potremmo semplicemente impostare una preferenza per le classi astratte invece di gestirla all'interno della classe del modello. Quindi un oggetto reale viene sempre iniettato.
BuskaMuza,
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.