Magento 2'de Özel Model Yüklemenin En İyi Yolu


15

Doğru yolu bulmak benim için zor olduğu için, aşağıda benim yaptığım en iyi uygulamayı bulabilirsiniz. Keyfini çıkarın, gerekirse İngilizcemi düzeltin ve eğer varsa yanılıyorum. :)

Düzenleme: ... ve ben bazı yönleriyle yanlış olduğunu öğrendim. Raphael'in cevapları daha fazla anlamama yardımcı olduktan sonra orijinal yayını güncelledim. Onun sayesinde !

Aşağıda kullanılan konsept :

Bu kavramlardan memnunsanız, aşağıdaki kodları ve açıklamaları anlamanız daha kolay olacaktır:

  • Enjeksiyon Bağımlılığı ( $this->variablekodlardaki her değişken enjekte edildiği için)
  • Hizmet Sözleşmesi ve Depo
  • Fabrika

Bağlam :

Sadece daha fazla içeriğe sahip olmak için, doğru şekilde yapılandırılmış bir modülümüz olduğunu hayal edin:

  • bir yöntem içeren bir blok sınıfı CustomBlock getCustomModel($id),
  • bu yöntem param içinde iletilen kimliğe dayalı bir CustomModel nesnesi döndürür,
  • CustomModel tipi, içindeki modele karşılık gelir \Vendor\Module\Model\CustomModel
  • Bu model kendi kaynak modeliyle birlikte gelir (in \Vendor\Module\Model\ResourceModel\CustomModel)
  • ve deposu (in \Vendor\Module\Model\CustomModelRepository) ile.

Soru :

  • Her şeyin CustomModel nesnesini yüklemesine izin vermek için en iyi uygulama nedir?

Kullanamazsın load()Bu yöntem kullanımdan kaldırıldığı için bir CustomModel nesnesinden .

İyi uygulama CustomModel Hizmet Sözleşmesini kullanmanız gerektiğini söylüyor. Hizmet sözleşmeleri veri arabirimleri (ör. CustomModelInterface) ve hizmet arabirimleri (ör. CustomModelRepositoryInterface). Yani bloğum şöyle görünüyor:

/ ** @var SlideRepositoryInterface * /
korumalı $ slideRepository;

/ **
 * CustomBlock oluşturucu
 * ...
 * @param CustomModelRepositoryInterface $ customModelRepository
 * ...
 * /
kamu işlevi __construct (
...
CustomModelRepositoryInterface $ customModelRepository
...
) {
    $ this-> customModelRepository = $ customModelRepository;
}

genel işlev getCustomModel ($ id) {
    $ this-> customModelRepository-> get ($ id) öğesini döndür;
}

Her şeyden önce, CustomModelRepositoryInterfacenesneyi yapıcıya enjekte ederiz ve getCustomModel()metodumuzda kullanırız.

Sınıfta Api\CustomModelRepositoryInterfaceçok fazla yok. Genellikle temel yöntemlerini ilan edecek (ama hiçbir şey farklı yapmasını önlemek): get, getList, save, delete, deleteById. Bu konunun amacı için aşağıdaki getyöntem beyanı aşağıdadır :

/**
 * Get info by id
 *
 * @param int $id
 * @return Data\CustomModelInterface
 * @throws \Magento\Framework\Exception\NoSuchEntityException
 */
public function get($id);

Tamam, ama benim CustomModel Arabirim benim blok yapıcı bağımlılık enjeksiyon tarafından çağrılırsa, kod nerede? Bu sorunun cevabı için Magento'ya bu arayüzü uygulayan sınıfı nerede bulabileceğinizi açıklamalısınız. Modülün etc / di.xml dosyasına şunları eklemeniz gerekir:

<preference for="Vendor\Module\Api\CustomModelRepositoryInterface" type="Vendor\Module\Model\CustomModelRepository" />

Yani CustomModelRepositoryInterfacesınıf bir servis arayüzüdür. Bunu uygularken veri arayüzlerini (en azından Vendor\Module\Api\Data\CustomModelInterfaceve Vendor\Module\Api\Data\CustomModelSearchResultsInterface) de uygulamanız gerekecektir . Modelinizin arayüzlerinizin her biri için satırları uygulaması Vendor\Module\Api\Data\CustomModelInterfaceve eklemesi gerekecektir <preference ... />. Son olarak, hizmet sözleşmesini her kullandığınızda, mySomethingInterfaceartık düşünmeyin mySomething: magento'nun di.xmltercihler mekanizmasını kullanmasına izin verin .

Peki, sırada ne var? CustomModelRepositoryInterfaceBlok yapıcıya enjekte ederken, bir CustomModelRepositorynesne elde ederiz . CustomModelRepositorybeyan yöntemini uygulamak zorundadır CustomModelRepositoryInterface. Yani bizde bu var Vendor\Module\Model\CustomModelRepository:

public function get ($ id) {
    $ customModel = $ this-> customModelFactory-> create ();
    $ CustomModel-> yük ($ id);
    if (! $ customModel-> getId ()) {
      yeni NoSuchEntityException atın (__ ('"% 1" kimliğine sahip CustomModel mevcut değil.', $ id));
    }
    return $ customModel;
}

Ne yapıyoruz ? CustomModelFabrika sayesinde boş bir nesne yaratıyoruz . Sonra CustomModelyük modeli yöntemini kullanarak veri yüklüyoruz. Sonra params olarak id ile NoSuchEntityExceptionyükleyemediğimizde bir CustomModeldöneriz. Ama her şey yolundaysa, model nesnesini geri veririz ve hayat devam eder.

Ama vay be ...! Bu örnekte bu nedir?

$customModel->load($id);

loadBaşlangıçtaki ile aynı itiraz yöntemi değil mi? Evet öyle. Bence bu bir utanç, ama bunu kullanmak zorunda çünkü bu load () yönteminde gönderilen bazı olaylar vardır ve geliştirici onları dinleyebilir (aşağıdaki Raphael'in cevabına bakınız).

Gelecekte Entity Manager tarafından tasarruf edeceğiz. Yeni bir Magento 2 konsepti olarak başka bir hikaye, ancak bir göz atmak istiyorsanız, Entity Manager zaten CMS'nin Kaynak Modeli'nde (v2.1) uygulandı:

public function load(AbstractModel $object, $value, $field = null)
{
    $pageId = $this->getPageId($object, $value, $field);
    if ($pageId) {
        $this->entityManager->load($object, $pageId);
    }
    return $this;
}

Yanıtlar:


16

En iyi uygulama: servis sözleşmesi ile

En iyi uygulama her zaman mümkün olduğunda hizmet sözleşmesini kullanmaktır. Sebeplerin listesini burada bulabilirsiniz: Magento 2: Hizmet sözleşmelerini kullanmanın faydaları nelerdir?

Hizmet sözleşmesinin nasıl uygulanacağı hakkında ayrıntılar için şu konuyu kontrol etmenizi öneririm: Magento 2'de özel bir modül için hizmet sözleşmesi nasıl uygulanır?

Hizmet sözleşmesi yoksa

Mevcut hizmet sözleşmesi yoksa, model veri havuzu getyöntemini kullanmalısınız. Bu yöntemi kullanarak, örneğin CategoryRepositorysınıf için magento önbellek sisteminden faydalanırsınız :

public function get($categoryId, $storeId = null)
{
    $cacheKey = null !== $storeId ? $storeId : 'all';
    if (!isset($this->instances[$categoryId][$cacheKey])) {
        /** @var Category $category */
        $category = $this->categoryFactory->create();
        if (null !== $storeId) {
            $category->setStoreId($storeId);
        }
        $category->load($categoryId);
        if (!$category->getId()) {
            throw NoSuchEntityException::singleField('id', $categoryId);
        }
        $this->instances[$categoryId][$cacheKey] = $category;
    }
    return $this->instances[$categoryId][$cacheKey];
}

Kaldırıldı load() yöntem

Magento 2, miras sistemini bırakarak ve yeni 2.1 EntityManager'ı kullanarak kompozisyon yoluyla uygulayarak standart CRUD sisteminden yavaşça uzaklaşıyor: Ayrıntıları burada bulabilirsiniz: Magento 2.1: varlık yöneticisini kullanarak

Ayrıca, kullanımdan kaldırılmış CRUD yöntemleri hakkında bu ilginç konuyu okumanızı öneririz: Soyut Modelde kullanım dışı kaydetme ve yükleme yöntemleri

Neden kaynak modeli yükünü kullanmıyorsunuz?

Bunun ana nedeni, kaynak modeli loadyöntemini kullanırsanız , yükleme loadyönteminin model yönteminde uygulanan bazı önemli bölümlerini atlamanızdır , bkz Magento\Framework\Model\AbstractModel:

public function load($modelId, $field = null)
{
    $this->_beforeLoad($modelId, $field);
    $this->_getResource()->load($this, $modelId, $field);
    $this->_afterLoad();
    $this->setOrigData();
    $this->_hasDataChanges = false;
    $this->updateStoredData();
    return $this;
}

Kaynak modeli loadyöntemini doğrudan çağırmak aşağıdaki etkiye sahip olacaktır:

  • _beforeLoad çağrılmaz: dolayısıyla olaylar gönderilmeden önceki model yükü
  • _afterLoad çağrılmaz: dolayısıyla olaylar gönderildikten sonra model yükü
  • saklanan veriler (eğer ararsanız örneğin çeşitli sorunlara yol açabilir güncellenmemesi prepareDataForUpdateitibaren Magento\Framework\Model\ResourceModel\Db\AbstractDb)

Teşekkürler Raphael, söylediğin her şey mantıklı ve bilgimi tamamlıyor. Ama neden KAndy, Marius'un özel modül kaynak modelinin load () yöntemini kullanabileceğini (cevabının altında) yorumladığını anlamıyorum? Bu Soyut Modelde [ magento.stackexchange.com/questions/114929/… kaydetme ve yükleme yöntemlerinde). Herhangi bir fikir ?
Nicolas PERNOT

@NicolasPERNOT temel olarak KAndy, hedefin her modül için SL (Hizmet Katmanı) olması olduğunu ve bir varlığı her yüklemeniz gerektiğinde bunun yapılması gerektiğini açıklar. Sanırım bir Magento Inc çalışanı olarak sizi aydınlatabileceğini söyleyerek yorum yapmanızı öneririm.
Digital Pianism'de Raphael

Sonunda orijinal gönderimi güncelledim. Raphael'in yardımın için teşekkürler.
Nicolas PERNOT

En azından Magento 2.2'de ResourceModel yüküne önemli olduğunu görüyorum, bu yüzden ResourceModel yöntemlerini doğrudan kullanmak doğru değil, değil mi?
Jānis Elmeris

Şu anda, Modeli Kaynak Modeli load()yöntemini kullanarak güvenli bir şekilde yükleyebiliriz . Kaynak Modeli modelin yöntemlerini kendi load()yönteminden çağırır : $model->beforeLoad() { $this->_beforeLoad() }ve$model->afterLoad() { $this->_afterLoad() }
sergei.sss

-2

Aşağıdaki ifadenin şu anda geçerli olmadığını düşünüyorum.

Why not using the resource model load

Magento\Framework\EntityManager\Observerklasörde tüm olayları bulabiliriz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.