Apakah ada alasan untuk lebih memilih $ model-> load () daripada kontrak layanan?

24

Saya mengerti bahwa cara yang disukai untuk bekerja di antara modul di Magento 2 adalah menggunakan kontrak layanan.

Jadi, jika saya ingin memuat suatu produk, saya menggunakan gudang produk:

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

yang dengan kontrak mengembalikan instance dari Magento\Catalog\Api\Data\ProductInterface.

Tapi saya juga bisa menggunakan cara lama, memanggil lapisan domain secara langsung:

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

Apakah ada kasus di mana ini perlu atau bermanfaat?

Devdocs mengatakan (sorot ditambahkan):

Modul dapat langsung memanggil modul lain. Solusi yang digabungkan secara ketat ini tidak direkomendasikan untuk sebagian besar situasi, tetapi terkadang tidak dapat dihindari .

[...]

Strategi Anda untuk memanggil kode lapisan-domain modul lain sangat tergantung pada konfigurasi unik dan kebutuhan sistem Anda.

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

Dan komentar pada pertanyaan terkait menyatakan:

menggunakan Repositori akan memberi Anda model data Produk ( Api/Data/Product), yang merupakan model Produk yang diubah menjadi DTO yang dumbed-down. Sesuatu untuk dipertimbangkan, karena mereka sangat berbeda

Tapi sejauh yang saya bisa lihat objeknya sama dalam kondisi normal, hanya tipe return per phpDoc berbeda ( Magento\Catalog\Api\Data\ProductInterface/ Magento\Catalog\Model\Product)

Fabian Schmengler
sumber

Jawaban:

23

Alasan untuk menggunakan ProductRepository's get/ getByIdbukannya load()metode ProductFatory , adalah karena yang pertama adalah tingkat yang lebih tinggi daripada yang terakhir.

A ProductRepository- sama seperti ProductFactory- mungkin mengembalikan Product model , tetapi bukan itu yang M2 ingin Anda pertimbangkan. Itu tidak apa \Magento\Catalog\Api\ProductRepositoryInterface::getById()'s blok doc kata. Dikatakan @return \Magento\Catalog\Api\Data\ProductInterface, yang merupakan antarmuka yang diterapkan model Produk .

SO, Anda harus menggunakan layer API bila memungkinkan, karena:

  • Api/Data lapisan digunakan di Api Web, juga
  • model dapat - dan mungkin akan - di refactored di beberapa titik; Api/Data/Producttidak akan.
  • Untuk mendapatkan produk di kelas Anda, Anda harus menyuntikkan pabrik beton ( ProductFactory) atau antarmuka ( ProductRepository). Saya tidak berpikir Anda ingin modul Anda mengandalkan apa pun selain antarmuka. Karenanya saya tidak setuju dengan jenis injeksi ini .

Saya menganggap itu hanya lapisan abstraksi kecil di atas model, untuk memenuhi API Web (REST, SOAP dll).

Mengutip jawaban ini :

Mudah-mudahan, Anda akan menyukai kontrak layanan ketika modul khusus Anda tidak akan rusak setelah rilis Magento 2 berikutnya (tentu saja jika Anda tidak melewati kontrak layanan dan menggunakan model / koleksi / model sumber daya secara langsung). Dan ketika Anda mulai mengonsumsi / mengekspos API web Magento 2, yang sekarang didasarkan pada kontrak layanan yang sama. Jadi Anda harus membuat perubahan hanya di satu tempat (mis. Via plugin) dan itu akan diterapkan di mana-mana. Ini tidak mungkin di Magento 1.

nevvermind
sumber
Tidak persis apa yang saya minta tetapi itu yang saya pikirkan juga, terima kasih untuk konfirmasi!
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?. Ya: ketika Anda perlu memanggil metode model dan bukan metode Api/Data/Product. Ini lebih baik? :)
nevvermind
Ya, itu masuk akal :)
Fabian Schmengler
14

Bagi saya, tidak ada alasan untuk menggunakan loadmetode di atas getById/ getmetode.

Saya tidak mengatakan bahwa saya benar tetapi beginilah cara saya melihat sesuatu.

Ok jadi inilah getByIdmetodenya ( getmetode ini serupa tetapi menggunakan sku bukan id):

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];
}

Karena Anda dapat melihat kode yang Anda tempel:

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

Merupakan bagian dari fungsi ini.

Namun, kondisi tambahan menggunakan instance yang di-cache untuk menghindari reload tambahan jika Anda sebelumnya telah menggunakan getByIdatau getmetode untuk id yang sama (atau sku dalam kasus getmetode) .

Anda mungkin berpikir bahwa alasan yang baik untuk menggunakan loadbisa untuk menghindari menggunakan contoh-contoh yang di-cache (dalam hal mana itu bisa menjadi alasan yang baik? Yang saya tidak tahu) tetapi getByIddan getmetode memiliki $forceReloadparameter yang dapat diatur ke true untuk hindari menggunakan instance cache tersebut.

Itu sebabnya bagi saya, tidak ada alasan bagus untuk menggunakan loadmetode over getByIdatau getmetode.

Raphael di Digital Pianism
sumber
2

Harap pahami perbedaan antara repositori dan koleksi.

Dalam contoh Anda, jika menggunakan repositori, Anda akan mendapatkan array Magento\Catalog\Api\Data\ProductInterfaceyang berbeda dari mendapatkan koleksi Magento\Catalog\Model\Product.

Repositori dan antarmuka data memberi Anda level antarmuka tinggi yang harus dijamin kompatibel di masa mendatang . Inilah sebabnya mengapa ini adalah pendekatan yang disarankan.

Semoga ini bisa membantu.

Phoenix128_RiccardoT
sumber