Kapan Kita Harus Menggunakan Gudang dan Pabrik di Magento 2?

75

Saya telah melalui beberapa tutorial di Magento 2, dan ini sedikit membingungkan saya. Saya dapat melihat pada dasarnya ada dua cara dimana kita dapat membaca / menulis entitas bisnis:

Ambil Data

Menggunakan Pendekatan Pabrik

$object = $this->myFactory->create();
$object->load($myId);

Menggunakan Pendekatan Repositori

$repo   = $this->myRepository();
$object = $repo->getById($myId);

Simpan Data

Menggunakan Pendekatan Pabrik

$object = $this->myFactory->create();
$object->load($myId);
$object->setData('something', 'somethingDifferent')->save();

Menggunakan Pendekatan Repositori

$repo   = $this->myRepository();
$object = $repo->getById($myId);
$object->setData('something', 'somethingDifferent');
$repo->save($object);

Saya juga bisa melihat bahwa, baik repositori dan kelas pabrik dapat diinjeksi menggunakan injeksi dependensi. Ini membingungkan setidaknya bagi saya.

Kapan kita harus menggunakan pendekatan repositori dan pendekatan pabrik? Apa praktik terbaik yang perlu kita ikuti?

Rajeev K Tomy
sumber
Contoh penggunaan Factory, CollectionFactory, dan Repositori yang baik dapat dilihat di \ Magento \ Setup \ Fixtures \ CategoryResolver
Ricardo Martins

Jawaban:

72

Jika ada repositori dan melakukan apa yang Anda butuhkan dengan baik, selalu lebih suka repositori.

Repositori adalah bagian dari Kontrak Layanan (ini adalah implementasi dari antarmuka Api), ini berarti mereka dimaksudkan sebagai antarmuka publik ke modul lain.

Gunakan Gudang untuk memuat penuh

$model->load()bukan bagian dari kontrak layanan. Saya punya pertanyaan tentang topik tertentu, Anda mungkin menemukan jawaban yang berguna: Apakah ada alasan untuk lebih memilih $ model-> load () daripada kontrak layanan?

Gunakan Pabrik untuk membuat entitas baru

Repositori tidak disertai dengan metode untuk membuat entitas baru, jadi dalam hal ini, Anda akan memerlukan pabrik. Tetapi gunakan pabrik untuk antarmuka , seperti Magento\Catalog\Api\Data\ProductInterfaceFactory- itu akan membuat implementasi yang tepat berdasarkan konfigurasi DI.

Kemudian gunakan repository->save()metode untuk menyimpannya.

Gunakan Pabrik Koleksi jika Anda membutuhkan lebih banyak kontrol

Berikut ini bukan praktik terbaik Magento resmi, tetapi saat ini, repositori tidak memberi Anda kontrol yang baik atas apa yang dimuat. API kriteria pencarian memungkinkan Anda menentukan filter, tetapi misalnya, tidak ada cara untuk memilih atribut EAV tertentu atau menentukan tabel indeks mana yang akan digabung.

Ini adalah detail implementasi, disembunyikan dari API kontrak layanan, tetapi seringkali detail implementasi ini penting dan Anda mendapatkan kinerja yang buruk jika Anda mengabaikannya. Karena itu, begitu repositori membatasi saya, saya tidak ragu lagi untuk menggunakan koleksi yang mendasarinya.

Fabian Schmengler
sumber
2
Bisakah Anda memberikan contoh kode tentang menggunakan Pabrik untuk membuat entitas baru , penjelasannya kehilangan beberapa detail dan sulit dimengerti. Terima kasih banyak.
Key Shang
1
@ Apakah ini membantu? devdocs.magento.com/guides/v2.2/extension-dev-guide/…
Fabian Schmengler
Terima kasih. tapi use the factory for the interface, such as Magento\Catalog\Api\Data\ProductInterfaceFactory - it will create the right implementation based on DI configuration.intinya yang tidak bisa saya mengerti, panduan dev tidak memperkenalkan InterfaceFactory , bagaimana cara menggunakan repository->save()metode untuk menyelamatkan entitas baru? Saya hanya bisa menggunakan pabrik untuk menyimpan entitas baru, bukan repositori.
Kunci Shang
@Key Shang, itu berarti bahwa antarmuka akan memberi Anda semua fungsi data yang ditetapkan untuk menyimpan masing-masing dan setiap kolom tabel jadi cobalah untuk menggunakan antarmuka sedapat mungkin untuk menyimpan catatan baru. Kelas InterfaceFactory dapat dibuat sebagai bagian dari kompilasi di: sehingga Anda dapat melihatnya di folder var / generation.
stevensagaar
@stevensagaar Terima kasih, saya bisa memahaminya sekarang.
Key Shang
21

Pertanyaan bagus.

Bahkan jika Repositori dan Pabrik mengizinkan kami mengakses Entitas, saya pikir kita harus fokus pada tanggung jawab mereka .

Dari dokumentasi Magento : "Pabrik adalah kelas layanan yang instantiate kelas yang tidak dapat disuntikkan, yaitu, model yang mewakili entitas database. Mereka membuat lapisan abstraksi antara ObjectManager dan kode bisnis."

Dari artikel Alan Storm : "Objek repositori bertanggung jawab untuk membaca dan menulis informasi objek Anda ke toko objek"

Interpretasi saya adalah: Jika tujuan kami adalah bekerja dengan benda yang tidak dapat disuntikkan (disebut "baru"), kami harus menggunakan Pabrik; jika fokus kita adalah mencari / membaca / menulis objek di dalam suatu toko objek kita harus menggunakan Gudang.

Ini adalah pendekatan idealis saya pada topik; perlu diingat bahwa implementasi aktual dapat memaksa kita untuk mengacaukan berbagai hal, seperti yang ditunjukkan oleh Alan.

Nikmati.

Alessandro Ronchi
sumber
5

Saya akan mengatakan langkah ke depan untuk mulai menggunakan repositori karena memungkinkan pemisahan kode antara pembacaan / penulisan data dan logika bisnis.

Ada artikel yang sangat rinci yang ditulis oleh Alan Storm tentang ini, menjelaskan cara menggunakan repositori tetapi juga melihat beberapa kelemahan dari metode baru ini: http://alanstorm.com/magento_2_understanding_object_repositories/

Juga, dari dokumentasi Magento, menjelaskan manfaat dari pendekatan baru ini: http://devdocs.magento.com/guides/v2.0/extension-dev-guide/service-contracts/service-contracts.html

Marina Vilcea
sumber
2
Terima kasih atas jawabannya. Saya benar-benar mendapatkan keraguan ini di kepala saya dari artikel alanstorm sendiri. :)
Rajeev K Tomy
3
Memang, itu membuat Anda berpikir, tetapi itu mungkin hal yang baik. Bahkan jika ini adalah praktik terbaik yang disarankan oleh Magento, itu tidak berarti pengembang tidak dapat mengajukan pertanyaan dan mengkritik beberapa aspeknya. Juga, masih ada situasi yang tidak tercakup oleh repositori. Namun, dalam konteks membangun ekstensi yang tidak akan rusak pada rilis mendatang menggunakan repositori harus dipertimbangkan. Juga, saya yakin mereka akan mengembangkan lebih lanjut dan menawarkan cakupan lebih lanjut tentang apa yang dibutuhkan pengembang.
Marina Vilcea
Saya 100% setuju dengan komentar Anda. Saya sangat berharap begitu. Juga tolong lihat jawaban fabian juga.
Rajeev K Tomy
Ya, saya melihat :) sudah mengangkat jawabannya. Terima kasih atas pertanyaannya!
Marina Vilcea
Lebih jauh, saya membaca di suatu tempat bahwa menggunakan metode manipulasi data tingkat rendah ok di install / upgrade skrip $setup->updateTableRow(...);atau pabrik, saya tidak yakin tetapi rasanya seperti argumen untuk menggunakan level yang lebih tinggi berlaku untuk area itu juga, bagaimana menurut Anda?
medmek
1

Semoga jawaban ini dapat membantu pengembang ekstensi lainnya juga.

Kita harus menyimpan model menggunakan Repositori saja.

  1. Model Pabrik di Magento 2 menyimpan data yang sangat terbatas.
  2. Di sisi lain, Model Repositori berisi semua data, jika atribut eav terkait dengan pelanggan, produk, dll.
  3. Untuk menyimpan model, selalu gunakan Repositori untuk menyimpan entitas apa pun, jika model pabrik digunakan untuk menyimpan model, itu menghapus semua atribut non-sistem eav terkait dengan entitas itu (pelanggan, produk, dll.).

  4. Untuk memuat tujuan model, Repositori adalah opsi terbaik untuk mendapatkan model menggunakan metode getById ().

Saya akan merekomendasikan untuk menggunakan Repository sebanyak mungkin khusus untuk tujuan penyelamatan model.

Sachin
sumber
1

Sekarang memuat, menyimpan, menghapus metode (model) sudah usang. Jadi kita dapat menggunakan model sumber daya atau repositori.

Magento sekarang menggunakan konsep manajer entitas untuk menyimpan, menghapus, memuat operasi.

Model sumber daya memiliki objek manajer entitas untuk memenuhi operasi tersebut.

$categoryModel = $this->_objectManager->create('\Magento\Catalog\Model\CategoryFactory')->create();        
  $categoryResource = $this->_objectManager->create('\Magento\Catalog\Model\ResourceModel\Category');        
  $categoryResource->load($categoryModel, 3);        
  echo $categoryModel->getName();
Siva Kumar Koduru
sumber