Menyuntikkan Ketergantungan ke dalam Magento 2 CRUD / Model Abstrak

12

Apakah mungkin untuk menyuntikkan ketergantungan ke model Magento 2 CRUD?

Itulah - Magento 2 memiliki kelas model abstrak dasar: Magento\Framework\Model\AbstractModel. Jika Anda ingin membuat objek model Buat, Baca, Perbarui, Hapus yang sederhana, Anda perluas kelas ini dengan kelas Anda sendiri.

class Foo extends Magento\Framework\Model\AbstractModel
{
}

Apakah mungkin untuk menyuntikkan dependensi dalam __constructmetode model Anda ? Ketika saya mencoba, saya akhirnya mendapatkan kesalahan berikut.

Kesalahan fatal: Tidak dapat membuat instance kelas abstrak Magento \ Framework \ Model \ ResourceModel \ AbstractResource

Pelakunya tampaknya menjadi AbstractModel's __constructmetode.

public function __construct(
    \Magento\Framework\Model\Context $context,
    \Magento\Framework\Registry $registry,
    \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
    \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
    array $data = []
) {

Ada dua jenis petunjuk dalam konstruktor ini ( Magento\Framework\Model\ResourceModel\AbstractResource, Magento\Framework\Data\Collection\AbstractDb) yang bukan antarmuka manajer objek Magento. Itu kelas abstrak. Ketika saya memperluas kelas ini dan mencoba untuk menambahkan ketergantungan saya yang disuntikkan

class Foo extends Magento\Framework\Model\AbstractModel
{
    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        array $data = [],
        \Package\Module\Model\Mine $mine,

    ) {
        //...
        parent::__construct($context, $registry, $resource, $resourceCollection, $data);

    }
}

Magento menebus ketika manajer objek mencoba untuk membuat instance kelas abstrak.

Saya bisa "memperbaiki" ini dengan memindahkan ketergantungan objek saya di depan kelas abstrak

    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,

        \Package\Module\Model\Mine $mine,

        \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        array $data = [],
    ) {  

Namun, ini mengubah urutan argumen. Di kelas yang sepenuhnya objek dikelola, ini tidak akan menjadi masalah. Namun, fakta bahwa petunjuk tipe kelas abstrak ini ada menyiratkan ada bagian dari sistem Magento yang akan secara manual (yaitu tidak melalui manajer objek atau DI) instantiate objek CRUD dan mengirimkan objek yang sesuai dengan petunjuk tipe dalam urutan tertentu .

Apakah ini aman? yaitu apakah kelas abstrak ini dalam konstruktor model abstrak hanya kode warisan, dan tidak digunakan? Atau apakah bagian-bagian dari sistem masih menggunakan ini, artinya tidak mungkin untuk menyuntikkan dependensi ke dalam model CRUD?

Alan Storm
sumber

Jawaban:

9

Pertama-tama konstruktor adalah api kelas pribadi. Fungsi konstruktor memiliki makna khusus dan tidak perlu harus memiliki daftar / urutan argumen yang sama seperti di kelas induk.

Apakah mungkin untuk menyuntikkan ketergantungan ke model Magento 2 CRUD?

Ya tentu saja.

Apakah ini aman?

Ya, tetapi Manajer Objek Magento menganggap bahwa semua parameter opsional ditempatkan di akhir daftar dan parameter yang diperlukan setelah opsional tidak akan diselesaikan.

$ resource, $ argumen resourceCollection adalah warisan tetapi masih banyak digunakan di kelas Model. Sebagian besar model menggunakan kode seperti ini untuk menginisialisasi kelas sumber daya dan koleksi.

protected function _construct() { 
    $this->_init('Magento\AdminNotification\Model\Resource Model\Inbox'); 
}

Inilah sebabnya mengapa parameter ini opsional. Tetapi, misalnya, dalam unit test kami melewati sumber daya atau koleksi tiruan dalam konstruktor untuk memungkinkan penggantian realisasi.

KAndy
sumber
@Kanday Apakah departemen teknik / arsitektur Magento pernah membuat pernyataan publik bahwa pesanan konstruktor untuk kelas inti tidak relevan? Atau apakah itu hanya harapan sebagian besar orang yang mengerjakannya?
Alan Storm
Saya tidak akan menyebutnya "tidak relevan". Hanya OM yang akan meneruskan argumen yang diperlukan ke konstruktor Anda dan itu tidak tergantung pada urutan di kelas induk. Selain itu, IN menggunakan nama-nama parameter, jadi sekarang lebih baik untuk tidak mengubah mereka (ini berbeda dari bahasa php, di mana Anda dapat mengubah nama parameter seperti yang Anda inginkan)
KAndy
Saya tidak yakin saya mengerti apa yang Anda katakan. Apakah Anda mengatakan bahwa, di beberapa titik di masa depan, kode sistem inti Magento mungkin mulai memperlakukan urutan argumen / parameter sebagai signifikan lagi?
Alan Storm
Saya percaya bahwa tidak
KAndy
Terima kasih lagi! FWIW, dan bagi para Googler, sepertinya ini hal yang aman untuk dilakukan. Dari apa yang saya tahu tidak ada kode sistem Magento yang secara otomatis membabi buta instantiates model dengan asumsi urutan parameter konstruktor.
Alan Storm
6

Ini tampaknya aman. Setidaknya, Magento melakukan ini di sejumlah tempat. Lihat metode __construct dalam daftar kelas (tidak eksklusif) berikut untuk contoh

  • \ Magento \ Tema \ Model \ Tema \ File
  • \ Magento \ Tema \ Model \ Desain
  • \ Magento \ Penjualan \ Model \ Pesan \ Creditmemo

Sayangnya, saya tidak dapat menjawab bagian lain dari pertanyaan Anda.

Nathan Toombs
sumber
4
  1. Bagaimana Anda menggunakan model Anda?
  2. Dalam kasus Anda $mineadalah parameter yang diperlukan , sementara $resource, $resourceCollectiondan $databersifat opsional . Parameter opsional harus selalu menjadi yang terakhir, jika tidak, tidak mungkin untuk bekerja dengan mereka seperti dengan opsional. Jadi sepertinya OK bagi saya bahwa Anda harus menentukan $minesebelum parameter opsional.
BuskaMuza
sumber
Kecuali parameter-parameter abstrak itu bukan parameter ketergantungan yang disuntikkan, dan jika kode sistem inti Magento mengharapkannya ada di sana, pindah $mineke bagian depan antrian akan membuat kesalahan. Jika kode sistem inti Magento tidak menggunakannya maka mengapa mereka ada di sana? Itulah pertanyaan yang saya coba sampaikan. Hanya karena saya dapat menggunakan model saya dengan parameter yang dipindahkan tidak membuatnya aman.
Alan Storm
Beberapa model mungkin masih menggunakan parameter opsional ini untuk lulus model sumber daya kustom. Misalnya, github.com/magento/magento2/blob/develop/app/code/Magento/…
BuskaMuza
Magento menggunakan refleksi untuk menentukan apakah parameternya opsional atau tidak. Dan PHP menganggap semua parameter berdiri di depan parameter yang diperlukan sebagaimana diperlukan . Jadi, jika Anda bergerak $minesebelum parameter opsional, mereka menjadi sangat opsional dan Magento hanya melewati nilai default ( null, array()). Jika Anda meletakkan parameter yang diperlukan setelah yang opsional, PHP menganggap parameter opsional sebagai yang diperlukan dan Magento mencoba untuk instantiate mereka (tetapi tidak ada preferensi untuk mereka).
BuskaMuza
Meskipun saya setuju bahwa itu terlihat membingungkan dan mungkin kita bisa mengatur preferensi untuk kelas abstrak daripada menangani di dalam kelas model. Jadi objek nyata selalu disuntikkan.
BuskaMuza