Magento 2 Helper instance


11

Ketika saya pikir saya mendapatkan kepala saya melilit sistem DI dari Magento 2, sesuatu muncul dan melepaskannya.
Saya melihat dalam kode inti berbagai cara untuk mengakses pembantu.
Misalnya Magento\Catalog\Controller\Category::_initCategoryada ini:

if (!$this->_objectManager->get('Magento\Catalog\Helper\Category')->canShow($category)) {
    return false;
}

Tetapi dalam Magento\Catalog\Block\Category\Viewhelper disuntikkan ke konstruktor

public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\Catalog\Model\Layer\Category $catalogLayer,
    \Magento\Framework\Registry $registry,
    \Magento\Catalog\Helper\Category $categoryHelper,
    array $data = array()
) {
    $this->_categoryHelper = $categoryHelper;
    $this->_catalogLayer = $catalogLayer;
    $this->_coreRegistry = $registry;
    parent::__construct($context, $data);
}

Ini membuat saya berpikir bahwa para pembantu harus diakses secara berbeda di dalam pengontrol dan blok (dan model) tetapi kemudian saya menemukan sebuah pengontrol di mana seorang pembantu dimasukkan ke dalam konstruktor Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute.

Tolong bersihkan kabut untuk saya.
Kapan saya harus menggunakan DI dan kapan saya harus menggunakan objectManager? dan mengapa?
Saya telah membaca pertanyaan ini: Instantiating Helpers in Magento 2 . Ini hanya pertanyaan lanjutan untuk itu.

Jawaban:


10

Saya lebih suka DI jika memungkinkan, karena menggunakan manajer objek sudah merupakan pelanggaran terhadap hukum demeter. Saat menggunakan manajer objek, dependensi ini hanya disembunyikan dalam logika metode.


Ya. Saya setuju. Saya akan menggunakan DI, tetapi saya ingin tahu mengapa ini dilakukan pada intinya? Mungkin seseorang belum bisa memperbaiki kelas yang saya sebutkan, belum?
Marius

Afaik mereka masih sering melakukan refactoring dan berharap mereka juga akan menyentuh tempat-tempat ini. Tetapi juga tidak tahu tentang prioritas, yang harus ada jika mereka ingin benar-benar merilis di beberapa titik. Jadi mungkin beberapa fitur baru atau praktik buruk lainnya akan diperbaiki terlebih dahulu.
Tobias

Bagaimana jika Anda memiliki kelas 10 fungsi dan HANYA 1 fungsi memerlukan model spesifik? Bukankah akan berlebihan (dari tampilan kinerja) untuk memuat model melalui injeksi konstruktor untuk masing-masing dari 10 fungsi sementara kita bisa memuatnya menggunakan object manager hanya di dalam 1 fungsi tunggal?
JohnyFree

6

Saya tidak tahu banyak tentang implementasi Magento, tetapi sepertinya ObjectManagerini adalah Locator Layanan .

Umumnya menggunakan Service Locator untuk mengakses dependensi pada suatu objek cukup buruk, periksa artikel ini .

Mendefinisikan ketergantungan Anda secara eksplisit melalui konstruktor adalah pendekatan yang jauh lebih baik. Ini membantu dalam pengujian unit dan menjalankan masalah waktu dengan layanan yang tidak ditentukan.

Menyuntikkan Object Manager ke kelas pada dasarnya menyuntikkan Registry ke kelas Anda yang memiliki akses ke semua layanan aplikasi Anda, yang jelas tidak benar.

Saya menggunakan ZF2 sedikit adil dan umumnya mendefinisikan kelas pabrik kecil untuk Layanan, Pengendali dan setiap kelas yang membutuhkan dependensi. Kelas-kelas pabrik ini memiliki akses ke Service Locator dan ambil semua layanan yang bergantung pada objek, dan menyuntikkan mereka melalui konstruktor. Menggunakan Service Locator di kelas Factory baik-baik saja karena sebagian besar membuang kode, misalnya seperti ini .

Pabrik-pabrik ini masih mudah diuji .

IMO, Gunakan injeksi konstruktor jika memungkinkan. Sekali lagi, saya tidak tahu terlalu banyak tentang implementasi Magento dan jika memiliki konsep Pabrik, dari sekilas itu terlihat seperti mendukung mereka, tetapi secara eksplisit mendefinisikan kelas Anda dan menggunakan Penunjuk Lokasi Layanan untuk membangunnya di kelas Pabrik adalah pendekatan yang jauh lebih bersih.

Ini dari seseorang yang memiliki paparan terbatas pada roti yang disebutkan di atas, jadi saya juga ingin mendengar pikiran / pengalaman orang lain tentang masalah ini!

Lebih banyak membaca


Terima kasih atas penjelasannya. Pertanyaan saya adalah "Mengapa ada 2 cara untuk mengakses pembantu di inti?" jadi ini agak di luar topik tapi itu menghilangkan beberapa keraguan lain yang saya miliki. :) Terima kasih.
Marius

Saya mungkin akan mengatakan bahwa itu adalah sesuatu yang baru saja belum di refactored. Entah itu atau itu mungkin hal yang mudah digunakan. Mengharuskan konsumen untuk selalu menyuntikkan semua ketergantungan mereka dalam Kontroler dapat dianggap sebagai kontra-produktif, terutama ketika melakukan RAD. Memberikan konsumen kedua cara untuk mengakses dependensi akan memungkinkan untuk pendekatan RAD tetapi masih memungkinkan bagi orang lain untuk secara eksplisit menentukan dependensi mereka jika mereka menghendaki.
Aydin Hassan

5

Salah satu cara lain untuk menggunakan helper (dalam templat) adalah:

$this->helper('[Vendor]\[Module]\Helper\[Helper Name]')->getMethodName();

Saya harap ini berguna jika Anda belum tahu.


ini mirip dengan menggunakan pengelola objek. Tidak yakin itu ide terbaik.
Marius

1
Metode di atas hanya untuk template sejauh yang saya tahu. Manajer objek digunakan dalam pengontrol, blok, model, dll.
rbncha

1
Ini tidak ada di ballpark yang sama dengan kode karena tidak ada ketergantungan kode pada templat. Template hanya konsumen dan tidak mencemari klien mana pun dengan enkapsulasi yang rusak.
demonkoryu

Saya tidak tahu apa yang ingin dikatakan demonkoryu. Tapi Cara terbaik untuk memanggil pembantu modul apa pun adalah ini. Ini adalah Magento. Seperti yang mereka katakan, setiap blok / kode bagian dimaksudkan untuk dapat dipanggil / dimodifikasi tanpa menyentuh inti. Jadi, semuanya saling terkait atau memiliki ketergantungan.
rbncha

2

Meskipun ini adalah pertanyaan lama, saya tidak yakin apakah Marius mendapatkan jawabannya. Saya percaya Marius bisa menjawabnya dengan lebih baik. Saya ingin menjawab singkatnya. Mengapa Magento 2 menyarankan untuk menggunakan DI bukan pembantu?

  • Membuat isolasi dalam pengujian unit mungkin / mudah
  • Mendefinisikan dependensi kelas secara eksplisit
  • Memfasilitasi desain yang baik (prinsip tanggung jawab tunggal (SRP) misalnya)
  • Menggunakan DI di modul Anda mengurangi risiko bug yang tidak kompatibel ketika Magento mengubah implementasi yang mendasari antarmuka tersebut. Ini adalah konsep penting untuk dipahami bagi pengembang ekstensi.

Mengapa M2 core mungkin tidak menggunakan DI dalam beberapa kasus?

  • Mengurangi jumlah kelas
  • Tidak membuat antarmuka yang tidak perlu
  • Tidak ada risiko bug yang tidak kompatibel

Meskipun modul Core catalog telah digunakan helper, ia telah menggunakan DI secara ekstensif. Dalam penelitian saya, saya menemukan Magento 2 menggunakan beberapa fungsi dalam file pembantu Katalog Core yang tidak cocok untuk Kontrak Servis.

Jika Anda harus secara eksplisit menggunakan kelas yang ditentukan Magento (seperti \ Magento \ Catalog \ Model \ Product), buat dependensi implisit secara eksplisit dengan bergantung pada implementasi konkret alih-alih antarmuka kontrak layanan.

Tidak diragukan lagi, pengembang ekstensi harus menggunakan DI bukan Magento1 seperti Helper. Saat menerapkan sesuai dengan pedoman Magento 2, dampaknya terbatas. Ketika melanggar rekomendasi, masalah terjadi.


Ya, saya mendapatkan jawaban saya sementara itu. Tetapi terima kasih telah meluangkan waktu untuk menjawab. Ini adalah informasi berharga bagi orang yang mencari ini secara online.
Marius
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.