Come devo salvare entità nuove o aggiornate dei modelli?


10

In Magento 2 abbiamo classi di repository. Il metodo classico save()usato pesantemente in Magento 1.9 è deprecato, se ho ragione, da 2.04 o 2.05. Stavo usando le fabbriche per creare un nuovo oggetto e dopo aver impostato le proprietà di nuovo, ad esempio il prodotto che ho chiamato save():

$productFactory->create()->setName()...->save()

D'altra parte abbiamo anche repository contenenti metodo save. Lo sto usando in poche parole in questo modo:

$product = $productFactory->create()->setName()... $productRepository->save($product)

Nel mio codice ho classi che funzionano in entrambi i modi. Ho anche notato che a volte modi diversi significano comportamenti diversi. Il modo con i repository ha fornito qualche ulteriore convalida dei dati forniti?

In che modo dovrei farlo?

Risposte:


10

Vediamo prima cosa succede se si utilizza il save()metodo direttamente su un productmodello come

/**
 * @var Magento\Catalog\Model\Product $product
 */
$product->save();

La classe del modello stesso è

Magento\Catalog\Model\Product

All'interno di questa classe, cerca la definizione del metodo save ().

Nessuno trovato giusto? Bene, c'è beforeSave () e afterSave (), ma non save () stesso. Interessante no?

Quindi, dobbiamo esaminare le classi principali di Magento\Catalog\Model\Product.

Dobbiamo attraversare Magento\Catalog\Model\AbstractModele Magento\Framework\Model\AbstractExtensibleModel, solo per arrivare finalmente a Magento\Framework\Model\AbstractModel.

Abbastanza sicuro, c'è un metodo save () qui e sembra qualcosa di simile

public function save()
{
    $this->_getResource()->save($this);
    return $this;
}

Vediamo ora, ogni volta che save () viene chiamato su qualsiasi modello, viene chiamato il metodo save () da questo AbstractModel, e l'implementazione è che il MODELLO RESOURCE esegue effettivamente il salvataggio.

Quest'ultimo non è sorprendente dato che siamo sempre, dal momento che come l'inizio del tempo in Magento 1.0, creando sia un modello che un modello di risorsa per quasi tutte le entità.


Ora diamo un'occhiata a come ProductRepositoryfunziona.

Consente di aprire il file

/vendor/magento/module-catalog/Api/ProductRepositoryInterface.php

Questa interfaccia richiede che esista un metodo save (), tra gli altri metodi.

Chi sta implementando questa interfaccia?

Consente di aprire il file

/etc/di.xml

e controlla la linea 10

<preference for="Magento\Catalog\Api\ProductRepositoryInterface" type="Magento\Catalog\Model\ProductRepository" />

Quindi, naturalmente troviamo all'interno l'implementazione del metodo save ()

/vendor/magento/module-catalog/Model/ProductRepository

e inizia sulla linea 444, assomigliando a qualcosa di simile

public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveOptions = false)
{
    $tierPrices = $product->getData('tier_price');

    try {
    .... other code here ....

Questo metodo prevede un oggetto $ product di tipo \Magento\Catalog\Api\Data\ProductInterfacepassato, ma per impostazione predefinita questo si risolve in Magento\Catalog\Model\Product.

Guardando in basso alla riga 500, tra l'altro try, vediamo qualcosa di simile

$this->resourceModel->save($product);

Hai indovinato bene! $this->resourceModelè di tipo \Magento\Catalog\Model\ResourceModel\Product, dichiarato come protectedproprietà sulla riga 77.

Quindi, di nuovo, in ResourceModelrealtà fa il risparmio.

Ma, tra le righe 444 e 500 è in realtà la risposta alla tua domanda. Tutto il codice eseguito qui, infatti, potrebbe eventualmente e porterà a differenze di comportamento tra il salvataggio diretto del modello e questo modo di salvare il repository.

Ad esempio il repository del prodotto otterrà ed elaborerà i collegamenti del prodotto se ignore_links_flagè impostato su 0, per prima cosa controlla se si tratta di un prodotto esistente ecc.

Probabilmente dobbiamo concludere che se in futuro dovesse essere necessario modificare il modo in cui il prodotto viene salvato, forse il modo migliore per farlo è quello di sostituire il repository del prodotto anziché il modello del prodotto.

Lo stesso vale per il salvataggio e l'aggiornamento dei prodotti. Preferirei utilizzare l'oggetto repository del prodotto.

Vi rimando gentilmente anche a /vendor/magento/module-cms/Model/PageRepository.php

Ecco come una pagina CMS verrebbe salvata tramite repository. Qui, le cose sono più semplici. L'ID negozio è impostato e il modello di risorsa viene chiamato per il salvataggio immediato.

Con quest'ultimo avviso, concluderai che in alcuni casi potrebbero non esserci molte differenze tra il repository e il salvataggio del modello, ma spero comunque che tu sia equipaggiato per individuarli ogni volta che è necessario.


1

Si consiglia di utilizzare direttamente le interfacce dati (ad es. \Magento\Catalog\Api\Data\ProductInterface) Anziché il modello e di utilizzare i repository per caricare e salvare i modelli.

Vedi la documentazione per gli sviluppatori Magento


1
ok - questo è il modo giusto per l'intera entità - ma solo per aggiornare il valore di qualche attributo - penso che non sia consigliabile caricare / salvare l'intera entità.
Bartosz Kubicki il
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.