Ok, jadi kemarin kami melakukan pembicaraan besar dengan orang lain dari komunitas Magento mengenai penggunaan langsung ObjectManager
di kelas / templat .
Saya sudah mengetahui alasan mengapa kita tidak boleh menggunakan ObjectManager secara langsung, mengutip Alan Kent :
Ada beberapa alasan. Kode akan berfungsi, tetapi merupakan praktik terbaik untuk tidak merujuk kelas ObjectManager secara langsung.
- Karena kami bilang begitu! ;-) (lebih baik dinyatakan sebagai kode konsisten adalah kode yang baik)
- Kode ini dapat digunakan dengan kerangka kerja injeksi ketergantungan yang berbeda di masa mendatang
- Pengujian lebih mudah - Anda memberikan argumen tiruan untuk kelas yang diperlukan, tanpa harus menyediakan ObjectManager tiruan
- Itu membuat dependensi lebih jelas - jelas apa kode tergantung melalui daftar konstruktor, daripada memiliki dependensi tersembunyi di tengah-tengah kode
- Ini mendorong programmer untuk berpikir tentang konsep-konsep seperti enkapsulasi dan modularisasi yang lebih baik - jika konstruktor menjadi besar, mungkin itu adalah tanda bahwa kode perlu refactoring
Dari apa yang saya lihat di StackExchange, banyak orang cenderung mencari solusi mudah / pendek / tidak direkomendasikan, misalnya sesuatu seperti ini:
<?php
//Get Object Manager Instance
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
//Load product by product id
$product = $objectManager->create('Magento\Catalog\Model\Product')->load($id);
Alih-alih melalui proses yang menyakitkan tetapi direkomendasikan :
- membuat modul
- mendeklarasikan preferensi
- menyuntikkan dependensi
- mendeklarasikan metode publik
Namun, dan inilah dilema, file inti Magento 2 sering memanggil ObjectManager secara langsung . Contoh cepat dapat ditemukan di sini: https://github.com/magento/magento2/blob/develop/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Form.php#L57
Jadi inilah pertanyaanku:
- Mengapa Magento melakukan apa yang mereka sarankan agar kita tidak lakukan? Apakah itu berarti ada beberapa kasus di mana kita harus menggunakan
ObjectManager
secara langsung ? Jika demikian, apa sajakah kasus-kasus itu? - Apa konsekuensi menggunakan ObjectManager secara langsung ?
sumber
The intent of zend-servicemanager is for use as an Inversion of Control container. It was never intended as a general purpose service locator [...]
. Yang berlaku untuk M2 juga. Periksa jugaThere are valid use cases
bagian yang juga berlaku di sini.Jawaban:
Anda seharusnya tidak menggunakan ObjectManager secara langsung!
Pengecualian dari aturan tersebut adalah:
__wakeup
,serialize
, dllsumber
Jawaban brutal: M2 adalah porta M1 - bukan penulisan ulang lengkap. Jadi jangan berasumsi bahwa semua kode M2 porting sempurna (sayangnya). Hanya karena Anda menemukan sesuatu dalam basis kode M2, itu tidak berarti "itu cara terbaik untuk melakukannya". Terkadang itu hanya "kita belum sempat memperbaikinya".
Kurang brutal: Sesuai tanggapan lain, terkadang Anda HARUS menggunakannya karena tidak ada alternatif. Lain waktu mungkin karena alasan kompatibilitas ke belakang. Dan kode kerangka kerja terkadang masuk akal menggunakannya secara langsung, karena itu adalah kode kerangka kerja. Tetapi jika saya harus menebak tanpa melihat kode, banyak yang benar-benar harus diperbaiki tetapi belum memiliki prioritas yang cukup tinggi untuk melakukannya.
Ingat saja nasihat pengasuhan yang baik: "Anak-anak, lakukan apa yang saya katakan, bukan apa yang saya lakukan!"
sumber
Anda seharusnya tidak pernah menggunakan
\Magento\Framework\App\ObjectManager::getInstance()
.Itu mengalahkan tujuan injeksi ketergantungan. Kami kembali
Mage::getModel()
.Manajer objek harus digunakan hanya di pabrik dan kemudian disuntikkan ke konstruktor.
Keuntungan menggunakan ini adalah lebih sedikit kode untuk ditulis. Tapi ini tidak membuatnya baik-baik saja.
Fakta bahwa ini masih digunakan dalam inti, adalah karena itu belum di refactored. Saya harap itu akan terjadi.
sumber
di.xml
untuk membuat kunci => peta nama kelas dan menyuntikkan peta itu ke konstruktor pabrik dan menggunakan pabrik untuk instantiate kelas melalui objectmanagerTanpa tahu cerita lengkapnya di sini adalah dugaan saya:
Selama pengembangan M2 tim Magento pada tahap tertentu berlari script otomatis yang menggantikan kejadian
Mage:getModel()
,Mage::getSingleton()
,$layout->createBlock()
, dll untuk menggunakan ObjectManager.Kemudian refactoring seharusnya memperbaikinya sebagai gantinya menggunakan injeksi ketergantungan yang tepat tetapi tidak ada cukup waktu / sumber daya untuk mengubah semua kejadian.
Juga tim Magento akhir-akhir ini tampaknya menggunakan ini sebagai mekanisme pelarian. Alih-alih melanggar implementasi yang ada (dengan perlu mengubah konstruktor) mereka hanya menyembunyikan ketergantungan baru melalui ObjectManager. Saya tidak bisa mengatakan saya setuju dengan pendekatan ini - menulis kode yang lebih buruk untuk menghindari jeda SM.
Saya pikir pertanyaan Anda sudah mencakup alasan yang cukup. Secara umum ia menciptakan dependensi tersembunyi, dengan kata lain dependensi dalam detail implementasi dan tidak terlihat dari konstruktor saja.
sumber
Seharusnya tidak menggunakan Manajer objek secara langsung!
Misalnya:
juga jika Anda bekerja dengan pengamat acara atau plugin, Anda tidak boleh menggunakannya secara langsung.
Anda bisa menggunakannya di Pabrik, tetapi kecuali bahwa Anda harus menyuntikkan Object Manager di Constructor terlebih dahulu maka Anda dapat menggunakan objeknya dalam metode Anda
Lebih disukai menggunakan:
1) mendeklarasikan objek pribadi:
2) menyuntikkan di konstruktor dan menginisialisasi:
3) gunakan dalam beberapa metode:
sumber
::getInstance()
Alasan utama bahwa pengembang sangat tidak disarankan untuk menggunakan Object Manager secara langsung adalah bahwa penggunaan langsung dari Object Manager menyebabkan ekstensi tidak dapat diinstal dalam mode rilis terkompilasi.
Jadi, bagi pelanggan Anda rusak menggunakan mode rilis, termasuk semua pelanggan di Magento Cloud.
Sepertinya sebagian besar pengembang (sekitar 75%) tidak menguji ekstensi mereka untuk melihat apakah mereka dapat diinstal dalam mode rilis, jadi jangan mengalami masalah yang ditimbulkan oleh penggunaan ObjectManager yang salah.
Pada 2017, Magento Marketplace menjalankan kompilasi dan menginstal tes pada semua ekstensi yang dijual melaluinya. Jika ekstensi Anda menggunakan Object Manager secara langsung, itu akan gagal tes ini dan ditolak dari Marketplace sampai Anda menyelesaikan masalah ini dan memuat ulang.
sumber
Anda dapat mencoba dengan membuat objek objectManager dan tidak boleh menggunakan objectManager secara langsung .
Gunakan sesuatu seperti,
sumber