Hizmet sözleşmelerinde $ model-> load () 'ı tercih etmek için bir neden var mı?


24

Magento 2'deki modüller arasında çalışmanın tercih edilen yolunun servis sözleşmelerini kullanmak olduğunu biliyorum.

Yani bir ürün yüklemek istersem, ürün deposunu kullanırım:

$product = $productRepository->getById($id);

bir örneği iade sözleşmesi gereğidir Magento\Catalog\Api\Data\ProductInterface.

Ancak bunun yerine eski adımı kullanabilirim, etki alanı katmanını doğrudan çağırmak:

$product = $productFactory->create()->load($id);

Bunun gerekli veya yararlı olacağı bir durum var mı?

Devdocs şöyle diyor (vurgu eklendi):

Bir modül doğrudan başka bir modüle çağrı yapabilir. Bu sıkıca bağlı çözüm çoğu durumda önerilmez, ancak bazen kaçınılmazdır .

[...]

Başka bir modülün etki alanı katmanı kodunu arama stratejiniz, sisteminizin benzersiz yapılandırmasına ve gereksinimlerine büyük ölçüde bağlıdır.

Kaynak: http://devdocs.magento.com/guides/v2.0/architecture/archi_perspectives/domain_layer.html

Ve ilgili bir soru üzerine bir yorum belirtti:

Havuzun kullanılması size aptal bir DTO'ya dönüştürülmüş bir Ürün modeli olan bir Ürün veri modeli ( Api/Data/Product) verecektir . Dikkate alınacak bir şey, oldukça farklı olduklarından

Ancak normal koşullarda nesnelerin aynı olduğunu görebildiğim kadarıyla, sadece phpDoc başına dönüş türleri farklıdır ( Magento\Catalog\Api\Data\ProductInterface/ Magento\Catalog\Model\Product)

Yanıtlar:


23

Bir ProductFatory yöntemi yerine ProductRepository'nin get/ getByIdyerine kullanılmasının nedeni load(), öncekininkinden daha yüksek bir seviyede olmasıdır.

A ProductRepository- tıpkı bir ProductFactory- bir Product model döndürebilir , ancak M2'nin göz önünde bulundurmasını istediği şey bu değildir . Budur değil neyi \Magento\Catalog\Api\ProductRepositoryInterface::getById()'ın doktor blok söylüyor. @return \Magento\Catalog\Api\Data\ProductInterfaceBir Ürün modelinin uyguladığı bir arayüz olan diyor .

SO, mümkün olduğunda API katmanını kullanmalısınız, çünkü:

  • Api/Data Web Api de katman kullanılır
  • modeller bir noktada - ve muhtemelen - tekrar kırılabilir; Api/Data/Productolmaz.
  • Sınıfınıza bir ürün almak için, bir somut fabrikaya ( ProductFactory) veya bir arayüze ( ProductRepository) enjekte etmeniz gerekir . Modülünüzün bir arayüz dışında başka bir şeye güvenmesini istediğinizi sanmıyorum. Dolayısıyla bu tür bir enjeksiyona katılmıyorum .

Web API'sine (REST, SOAP vb.) Hitap etmek için modellerin üzerinde başka bir küçük soyutlama katmanı olduğunu düşünüyorum .

Bu cevaptan alıntı :

Umarım, özel modülünüz Magento 2'nin bir sonraki sürümlerinden sonra kırılmayacaksa servis sözleşmelerini seveceksiniz (tabii ki servis sözleşmelerini atlamazsanız ve doğrudan modelleri / koleksiyonları / kaynak modellerini kullanırsanız). Ve şimdi aynı hizmet sözleşmelerine dayanan Magento 2 web API'sini tüketmeye / göstermeye başladığınızda. Yani sadece tek bir yerde değişiklik yapmanız gerekiyor (örneğin, eklenti aracılığıyla) ve bunlar her yere uygulanacak. Magento 1'de bu imkansızdı.


Tam olarak istediğim şey değildi, ama düşündüğüm de buydu, onay için teşekkürler!
Fabian Schmengler

1
But I could also use the old way instead, calling the domain layer directly: (use factory). Is there any case where this would be necessary or useful?. Evet: Bir modelin yöntemini çağırmanız gerektiğinde, bir yöntem değil Api/Data/Product. Bu daha mı iyi? :)
nevvermind

Evet, bu mantıklı :)
Fabian Schmengler

14

Bana göre, loadyöntemi getById/ getyöntem üzerinde kullanmak için hiçbir neden yoktur .

Haklı olduğumu söylemiyorum ama işte bazı şeyleri görüyorum.

Tamam, işte getByIdyöntem ( getyöntem benzer ancak kimlik yerine sku kullanır):

public function getById($productId, $editMode = false, $storeId = null, $forceReload = false)
{
    $cacheKey = $this->getCacheKey(func_get_args());
    if (!isset($this->instancesById[$productId][$cacheKey]) || $forceReload) {
        $product = $this->productFactory->create();
        if ($editMode) {
            $product->setData('_edit_mode', true);
        }
        if ($storeId !== null) {
            $product->setData('store_id', $storeId);
        }
        $product->load($productId);
        if (!$product->getId()) {
            throw new NoSuchEntityException(__('Requested product doesn\'t exist'));
        }
        $this->instancesById[$productId][$cacheKey] = $product;
        $this->instances[$product->getSku()][$cacheKey] = $product;
    }
    return $this->instancesById[$productId][$cacheKey];
}

Yapıştırdığınız kodu görebileceğiniz gibi:

$productFactory->create()->load($id);

Bu fonksiyonun bir parçası.

Ancak, ekstra bir durum örneklerini önbelleğe kullanımları önceden kullanmış olduğunuz durumda ekstra bir reload kaçınmak getByIdveya get(durumunda veya sku aynı kimliği için yöntem getyöntemiyle) .

Sen kullanım için iyi bir neden düşünebilir load(bu durumda ben bilmiyorum? İyi bir neden olabilir) bu önbelleğe alınmış örnekleri kullanarak önlemek için olabilir ama getByIdve getyöntemleri var $forceReloadsadık olarak ayarlanabilir parametre Bu önbellek örneklerini kullanmaktan kaçının.

Bu yüzden benim için loadyöntem getByIdveya getyöntem kullanmanın iyi bir nedeni yok .


2

Lütfen depolar ve koleksiyonlar arasındaki farkı anlayın.

Örneğinizde, depolar kullanıyorsanız, Magento\Catalog\Api\Data\ProductInterfacebunun bir koleksiyonunu almaktan farklı bir dizi elde edersiniz Magento\Catalog\Model\Product.

Depolar ve veri arayüzü , gelecekteki sürümlerde uyumlu olması garanti edilmek üzere size yüksek bir arayüz seviyesi sunar . Bu yüzden önerilen yaklaşım budur.

Umarım yardımcı olur.

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.