Injection de dépendances dans un modèle CRUD / abstrait de Magento 2


12

Est-il possible d'injecter une dépendance dans un modèle Magento 2 CRUD?

C'est - Magento 2 a une classe de modèle abstrait de base: Magento\Framework\Model\AbstractModel. Si vous souhaitez créer un simple objet Créer, lire, mettre à jour, supprimer un modèle, vous étendez cette classe avec votre propre classe.

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

Est-il possible d'avoir injecté des dépendances dans la __constructméthode de votre modèle ? Quand j'essaye, je finis par obtenir l'erreur suivante.

Erreur fatale: impossible d'instancier la classe abstraite Magento \ Framework \ Model \ ResourceModel \ AbstractResource

Le coupable semble être la AbstractModelde » __constructméthode.

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 = []
) {

Il existe deux types d'indices dans ce constructeur ( Magento\Framework\Model\ResourceModel\AbstractResource, Magento\Framework\Data\Collection\AbstractDb) qui ne sont pas des interfaces du gestionnaire d'objets Magento. Ce sont des classes abstraites. Quand j'étends cette classe et essaie d'ajouter ma dépendance injectée

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 échoue lorsque le gestionnaire d'objets essaie d'instancier les classes abstraites.

Je peux "corriger" cela en déplaçant ma dépendance d'objet devant les classes abstraites

    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 = [],
    ) {  

Cependant, cela a changé l'ordre des arguments. Dans une classe entièrement gérée par des objets, ce ne serait pas un problème. Cependant, le fait que ces indications de type de classe abstraite impliquent qu'il existe des parties du système Magento qui vont manuellement (c'est-à-dire pas via le gestionnaire d'objets ou DI) instancier des objets CRUD et transmettre des objets qui sont conformes aux indications de type dans cet ordre spécifique .

Est-ce sûr? ie Ces classes abstraites dans le constructeur d'un modèle abstrait ne sont-elles que du code hérité et ne sont-elles pas utilisées? Ou certaines parties du système les utiliseront-elles encore, ce qui signifie qu'il n'est pas possible d'injecter des dépendances dans un modèle CRUD?

Réponses:


9

Tout d'abord, le constructeur est une API privée de classe. La fonction constructeur a une signification spéciale et ne nécessite pas d'avoir la même liste / ordre d'arguments que dans la classe parent.

Est-il possible d'injecter une dépendance dans un modèle Magento 2 CRUD?

Oui bien sûr.

Est-ce sûr?

Oui, mais Magento Object Manager suppose que tous les paramètres facultatifs sont placés à la fin de la liste et les paramètres requis après facultatif ne seront pas résolus.

Les arguments $ resource, $ resourceCollection sont hérités mais toujours largement utilisés dans les classes Model. La plupart des modèles utilisent du code comme celui-ci pour initialiser la classe de ressources et de collection.

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

C'est pourquoi ces paramètres sont facultatifs. Mais, par exemple, dans le test unitaire, nous passons une maquette de ressource ou de collection dans le constructeur pour permettre de remplacer la réalisation.


@Kanday Le département d'ingénierie / architecture de Magento a-t-il déjà déclaré publiquement que l'ordre des constructeurs pour les classes de base n'est pas pertinent? Ou est-ce juste l'espoir de la plupart des gens qui y travaillent?
Alan Storm

Je ne l'appellerai pas "hors de propos". Seul l'OM transmettra les arguments requis à votre constructeur et cela ne dépend pas de l'ordre dans la classe parent. De plus, IN utilise des noms de paramètres, alors maintenant il vaut mieux ne pas changer leurs (c'est différent du langage php, où vous pouvez changer les noms des paramètres comme vous le souhaitez)
KAndy

Je ne suis pas sûr de comprendre ce que vous dites. Êtes-vous en train de dire qu'à un moment donné dans le futur, le code système principal de Magento pourrait recommencer à traiter l'ordre des arguments / paramètres comme significatif?
Alan Storm

Je crois que non
KAndy

Merci encore! FWIW, et pour les Googleurs, cela semble être une chose sûre à faire. D'après ce que je peux dire, il n'y a pas de code système Magento qui instancie automatiquement et aveuglément un modèle en supposant l'ordre des paramètres du constructeur.
Alan Storm

6

Cela semble sûr. Au moins, magento fait cela à plusieurs endroits. Voir les méthodes __construct dans la liste de classes (non exclusive) suivante pour des exemples

  • \ Magento \ Theme \ Model \ Theme \ File
  • \ Magento \ Thème \ Modèle \ Conception
  • \ Magento \ Sales \ Model \ Order \ Creditmemo

Malheureusement, je ne peux pas répondre à l'autre partie de votre question.


4
  1. Comment utilisez-vous votre modèle?
  2. Dans votre cas, $mineun paramètre est requis , tandis que $resource, $resourceCollectionet $datasont facultatifs . Les paramètres facultatifs devraient toujours durer, sinon il est tout simplement impossible de travailler avec eux comme avec facultatif. Il me semble donc que vous devez spécifier $mineavant tout paramètre facultatif.

Sauf que ces paramètres abstraits ne sont pas des paramètres injectés dans les dépendances, et si le code du système principal de Magento s'attend à ce qu'ils se déplacent $minevers le début de la file d'attente, cela créera des erreurs. Si le code du système de base Magento ne les utilise pas, pourquoi sont-ils là? C'est la question que j'essaie de comprendre. Ce n'est pas parce que je suis capable d'utiliser mon modèle avec le paramètre déplacé que cela est sûr.
Alan Storm

Certains modèles peuvent toujours utiliser ces paramètres facultatifs pour transmettre un modèle de ressource personnalisé. Par exemple, github.com/magento/magento2/blob/develop/app/code/Magento/…
BuskaMuza

Magento utilise la réflexion pour déterminer si le paramètre est facultatif ou non. Et PHP considère tous les paramètres se tenant devant le paramètre requis comme requis . Donc, si vous vous déplacez $mineavant les paramètres facultatifs, ils deviennent vraiment facultatifs et Magento passe juste les valeurs par défaut ( null, array()). Si vous placez un paramètre obligatoire après les paramètres facultatifs, PHP considère les paramètres facultatifs comme des paramètres obligatoires et Magento a essayé de les instancier (mais il n'y a aucune préférence pour eux).
BuskaMuza

Bien que je convienne que cela semble confus et que nous pourrions peut-être simplement configurer une préférence pour les classes abstraites au lieu de la gérer à l'intérieur de la classe modèle. Un véritable objet est donc toujours injecté.
BuskaMuza
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.