Parce qu'il était difficile pour moi de trouver le bon chemin, vous pouvez trouver ci-dessous la meilleure pratique que j'ai faite. Profitez-en, corrigez mon anglais si nécessaire et dites-moi que je me trompe si je le suis. :)
Edit: ... et j'ai découvert que j'avais tort sur certains aspects. J'ai donc mis à jour le message d'origine après que les réponses de Raphaël m'ont aidé à mieux comprendre. Grâce à lui !
Concept utilisé ci - dessous :
Il vous sera plus facile de comprendre les codes et les explications ci-dessous si vous êtes à l'aise avec ces concepts:
- Dépendance à l'injection (car toutes les
$this->variable
variables des codes sont injectées) - Contrat de service et référentiel
- Usine
Contexte :
Juste pour avoir plus de contexte, imaginez que nous avons un module correctement construit avec:
- une classe de bloc CustomBlock contenant une méthode
getCustomModel($id)
, - cette méthode renvoie un objet CustomModel basé sur l'ID passé dans param,
- Le type CustomModel correspond au modèle dans
\Vendor\Module\Model\CustomModel
- Ce modèle est livré avec son modèle de ressource (en
\Vendor\Module\Model\ResourceModel\CustomModel
) - et avec son référentiel (en
\Vendor\Module\Model\CustomModelRepository
).
Question :
- Quelle est la meilleure pratique pour laisser le tout charger un objet CustomModel?
Vous ne pouvez pas utiliser le à load()
partir d'un objet CustomModel car cette méthode est déconseillée.
La bonne pratique indique que vous devez utiliser le contrat de service CustomModel. Les contrats de service sont des interfaces de données (par exemple CustomModelInterface) et des interfaces de service (par exemple CustomModelRepositoryInterface). Donc, mon bloc ressemble à ceci:
/ ** @var SlideRepositoryInterface * / $ slideRepository protégé; / ** * Constructeur CustomBlock * ... * @param CustomModelRepositoryInterface $ customModelRepository * ... * / fonction publique __construct ( ... CustomModelRepositoryInterface $ customModelRepository ... ) { $ this-> customModelRepository = $ customModelRepository; } fonction publique getCustomModel ($ id) { return $ this-> customModelRepository-> get ($ id); }
Tout d'abord, nous injectons l' CustomModelRepositoryInterface
objet dans le constructeur et nous l'utilisons dans notre getCustomModel()
méthode.
Dans la classe, Api\CustomModelRepositoryInterface
il n'y en a pas beaucoup. En général (mais rien ne vous empêche de le faire différemment) vous déclarer des méthodes de base: get
, getList
, save
, delete
, deleteById
. Aux fins de cette rubrique, voici simplement la get
déclaration de méthode:
/**
* Get info by id
*
* @param int $id
* @return Data\CustomModelInterface
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function get($id);
Ok, mais si mon interface CustomModel est appelée par injection de dépendance dans mon constructeur de bloc, où est le code? Pour répondre à cette question, vous devez expliquer à Magento où trouver la classe implémentant cette interface. Dans le fichier etc / di.xml du module, vous devez ajouter:
<preference for="Vendor\Module\Api\CustomModelRepositoryInterface" type="Vendor\Module\Model\CustomModelRepository" />
La CustomModelRepositoryInterface
classe est donc une interface de service. En l'implémentant, vous devrez implémenter également des interfaces de données (au moins Vendor\Module\Api\Data\CustomModelInterface
et Vendor\Module\Api\Data\CustomModelSearchResultsInterface
). Votre modèle devra implémenter Vendor\Module\Api\Data\CustomModelInterface
et ajouter des <preference ... />
lignes pour chacune de vos interfaces. Enfin, à chaque fois que vous utilisez un contrat de service, ne pensez mySomethingInterface
plus mySomething
: laissez magento utiliser le di.xml
mécanisme des préférences.
Ok, qu'est-ce qui vient ensuite? Lorsque nous injectons CustomModelRepositoryInterface
dans le constructeur de blocs, nous obtenons un CustomModelRepository
objet. CustomModelRepository
doit implémenter la méthode declare in CustomModelRepositoryInterface
. Nous avons donc ceci dans Vendor\Module\Model\CustomModelRepository
:
fonction publique get ($ id) { $ customModel = $ this-> customModelFactory-> create (); $ customModel-> load ($ id); if (! $ customModel-> getId ()) { lever une nouvelle NoSuchEntityException (__ ('CustomModel avec l'ID "% 1" n'existe pas.', $ id)); } return $ customModel; }
Que faisons-nous? Nous créons un CustomModel
objet vide grâce à l'usine. Ensuite, nous chargeons les données en CustomModel
utilisant la méthode du modèle de charge. Ensuite, nous renvoyons un NoSuchEntityException
si nous n'avons pas réussi à charger CustomModel
l'identifiant dans les paramètres. Mais si tout va bien, nous retournons l'objet modèle et la vie continue.
Mais wow ...! Dans cet exemple, qu'est-ce que c'est?
$customModel->load($id);
N'est-ce pas la même load
méthode obsolète qu'au début? Oui, ça l'est. Je pense que c'est dommage, mais vous devez l'utiliser car dans cette méthode load () il y a des événements distribués et le développeur pourrait les écouter (voir la réponse de Raphael ci-dessous).
À l'avenir, nous serons enregistrés par Entity Manager. C'est une autre histoire en tant que nouveau concept Magento 2, mais si vous voulez jeter un œil, Entity Manager est déjà implémenté dans le modèle de ressource de la page CMS (v2.1):
public function load(AbstractModel $object, $value, $field = null)
{
$pageId = $this->getPageId($object, $value, $field);
if ($pageId) {
$this->entityManager->load($object, $pageId);
}
return $this;
}
la source
load()
méthode du modèle de ressource . Le modèle de ressource appelle les méthodes du modèle à partir de sa propreload()
méthode:$model->beforeLoad() { $this->_beforeLoad() }
et$model->afterLoad() { $this->_afterLoad() }
Je pense que la déclaration suivante n'est pas valable maintenant.
nous pouvons trouver le
Magento\Framework\EntityManager\Observer
dossier de tous les événements.la source