Apa yang saya lakukan ketika ekstensi menimpa kelas secara global dan saya ingin menggunakan yang asli?

42

Kami menggunakan ekstensi yang secara global akan menimpa blok Mage_Catalog_Block_Product_List_Toolbar.

<global>
    <blocks>
        <catalog>
            <rewrite>
                <product_list_toolbar>Amasty_Shopby_Block_Catalog_Product_List_Toolbar</product_list_toolbar>
            </rewrite>
        </catalog>
    </blocks>
</global>

Sementara ekstensi berfungsi dalam konteks kategori navigasi berlapis, kelas yang ditulis ulang tidak berfungsi dengan baik ketika kami menyisipkan daftar produk yang sewenang-wenang ke tampilan lain (khusus) dalam modul internal kami sendiri. Jika kami menghapus ekstensi yang ditimpa hanya untuk tujuan pengujian, semuanya berfungsi dengan baik.

Bagaimana kita bisa membatalkan penulisan ulang ekstensi hanya untuk controller kita sendiri, tanpa mengedit kode komunitas pengembang ekstensi?

Aaron Pollock
sumber
2
Jika Anda mengubah kelas Anda mungkin akan merusak ekstensi Shopby tetapi ... Jangan pernah mencoba ini namun Anda mungkin hanya ingin menulis ulang kelas ekstensi itu di ekstensi Anda sendiri Your_Extension_Block_Catalog_Product_List_Toolbar meluas Amasty_Shopby_Block_Catalog_Product_List_Toolbar
Sander Mangel
Dari apa yang bisa saya katakan, Magento hanya memungkinkan satu <rewrite>per kelas, jadi meskipun saya bisa membuat kelas saya sendiri memperluas kelas inti, saya tidak yakin bagaimana saya bisa membuatnya bekerja melalui getBlock('catalog/product_list_toolbar')metode pabrik.
Aaron Pollock
Jika ekstensi ini berbayar, Anda harus menghubungi dukungan Amasty, ini terlihat sebagai bug
Fra
apakah Anda berhasil menemukan masalah? apa yang menyebabkan masalah yang Anda hadapi (yang berfungsi di kelas diperluas)?
FlorinelChis
1
@ AaronPollock mungkin, tetapi masalah ini masih bisa muncul dari ekstensi yang menimpa hal-hal seluas yang dibutuhkan. Mungkin kita akan lebih baik memeriksa kembali model warisan itu sendiri. Mungkin campuran atau sifat akan membantu.
kojiro

Jawaban:

25

Peringatan: Tidak ada cara yang dirancang untuk melakukan apa yang Anda minta dalam sistem. Berikut ini harusnya berhasil, tetapi saya belum pernah mencobanya secara luas pada sistem produksi, dan mungkin ada situasi di mana itu akan menyebabkan lebih banyak masalah yang layak. Hanya lanjutkan jika Anda merasa nyaman dengan masalah debug yang terkait dengan mengubah penulisan ulang sistem kerja.

Langkah 1 sedang membatalkan penulisan ulang. Pohon konfigurasi Magento dapat diubah saat runtime. Jadi, jika Anda menjalankan kode berikut

$config = Mage::getConfig();        
$config->setNode(
    'global/blocks/catalog/rewrite/product_list_toolbar',
    'Mage_Catalog_Block_Product_List_Toolbar'
);

Kemudian Magento akan instantiate Mage_Catalog_Block_Product_List_Toolbarblok asli untuk sisa permintaan.

Langkah 2 menentukan di mana harus memanggil ini dalam modul Anda. Karena ini hanya untuk controller Anda dan itu menulis ulang sebuah blok yang tidak akan dipakai sampai akhir controller Anda, saya akan menambahkan metode ke kelas controller Anda seperti ini

protected function _undoRewrites()
{
    $config = Mage::getConfig();        
    $config->setNode(
        'global/blocks/catalog/rewrite/product_list_toolbar',
        'Mage_Catalog_Block_Product_List_Toolbar'
    );    
}

lalu panggil metode ini di awal setiap tindakan Anda

public function indexAction()
{
    $this->_undoRewrites();
    $test = Mage::getSingleton('core/layout')->createBlock('catalog/product_list_toolbar');        
    var_dump($test);
}

Ini mungkin tampak sedikit kikuk, tapi saya pikir itu ide yang bagus untuk menjadi kikuk (yaitu jelas) ketika Anda menjadi pintar dengan objek sistem Magento. Tempat lain untuk ini bisa menjadi controller_action_predispatchatau controller_action_predispatch_front_controller_actionperistiwa dan / atau diterapkan kondisional.

Ingat saja penulisan ulang tidak akan dibatalkan sampai metode ini dipanggil. Itu berarti jika Anda mencoba untuk instantiate blok sebelum memanggil _undoRewrites, kelas yang ditulis ulang akan digunakan untuk instantiate objek.

Alan Storm
sumber
19

Solusi 1:
Anda dapat mencoba untuk instantiate kelas secara langsung (cara php) di controller Anda

dari pada

$this->getLayout()->createBlock('catalog/product_list_toolbar');

sesuatu seperti:

$block = New Magento_Catalog_Product_List_Toolbar;
$this->getLayout()->addBlock(....);

Solusi 2:
Pendekatan lain akan membuat kelas baru, dalam modul Anda, yang memperluas kelas asli dan menggunakannya.

Solusi 3:
Kalau tidak, jika ekstensi tidak crypted (kita semua suka open source :) Anda dapat mencoba mencari tahu mengapa itu merusak barang-barang Anda

Fra
sumber
Solusi 2 memang berfungsi (solusi pragmatis) tetapi tidak bagus karena saya tidak bisa melakukan yang kedua rewritepada kelas dasar yang sama. Oleh karena itu metode pabrik tidak akan berfungsi (Anda sudah menyadari ini saya pikir sudah). Mungkin tidak ada cara Magento untuk melakukan ini, tapi mari kita bertahan sedikit untuk melihat apakah ada cara yang lebih baik.
Aaron Pollock
Solusi 2 adalah apa yang akan saya ikuti ... Saya bersiap untuk menyarankan itu sampai saya melihat jawaban Francesco. ;)
davidalger
1
Meskipun saya suka solusi 2 yang terbaik, catatan untuk solusi 1: Anda juga dapat memberikan nama kelas yang lengkap untuk membuatBlock (seperti $this->getLayout()->createBlock("Mage_Catalog_Block_Product_List_Toolbar")ketika Anda berada dalam konteks kelas blok). Jika tidak ada /dalam parameter Magento hanya akan menggunakan string apa adanya untuk mencari kelas.
Matthias Zeis
1
@ Harun Pollock, Anda BISA melakukan penulisan ulang kedua pada kelas dasar yang sama. Cukup beri nama namespace modul sebagai Z (huruf apa saja setelah A) dan magento akan menggunakannya sebagai ganti Amasty.
Amasty
5

Jika ada beberapa penulisan ulang untuk alias kelas yang sama, maka yang terakhir loader konfigurasi Magento diurai dari config.xml "menang". Saya akan menyerang masalah ini dengan:

  1. Buat ekstensi baru Anda sendiri.
  2. Tulis ulang catalog/product_list_toolbarekstensi Anda
  3. Mintalah blok Anda diperpanjang, Mage_Catalog_Block_Product_List_Toolbarbukan kelas Amasty.
  4. Beri komentar dengan bebas kepada kelas Anda yang menjelaskan bahwa konflik penulisan ulang ini disengaja. Anda tidak ingin pengembang lain yang menjalankan MageRun mencoba dan "memperbaiki" konflik penulisan ulang yang baru saja Anda buat.
  5. Tambahkan dependensi pada file app / etc / modules / blah.xml ekstensi Anda untuk memastikan ekstensi Anda dimuat setelah Amasty.
Jim OHalloran
sumber
1

Mirip dengan apa yang disarankan Francesco di atas, tetapi saya yakin Anda benar-benar dapat memasukkan nama kelas penuh ke getModel. Dengan cara ini, Anda agak masih melakukan hal yang sama, tetapi menggunakan metode inti untuk melakukannya. Saya tidak sepenuhnya yakin pro / kontra untuk metode ini, tetapi berpikir saya akan membuang ini di luar sana sebagai ide.

Mage::getModel('Mage_Catalog_Block_Product_List_Toolbar');

Di samping catatan, saya percaya ini akan menjadi cara standar untuk memuat kelas di Magento2.

jmspldnl
sumber
1

Anda perlu melakukan sedikit perubahan pada kode ekstensi saya takut. Jangan menulis ulang kelas di Anda sendiri config.xmllagi, cukup ubah Amasty_Shopby_Block_Catalog_Product_List_Toolbaruntuk memperluas kelas Anda yang pada gilirannya meluas Mage_Catalog_Block_Product_List_Toolbar.

Paul Grigoruta
sumber
Saya melihat kode ekstensi seperti kode inti - bisnis orang lain (untuk mempertahankan kemampuan meningkatkan dengan bersih). Pasti ada cara yang menghindari menyentuhnya. Juga, masalahnya adalah kelas Amasty memecah fungsionalitas inti dalam konteks daftar produk yang sewenang-wenang. Saya tidak menyuntikkan fungsionalitas saya sendiri; Saya perlu menghidupkan kembali fungsionalitas inti. Kelas saya sendiri, jika saya mengikuti solusi Anda, akan kosong dan setiap upaya perbaikan yang saya lakukan di sana akan ditimpa oleh kelas Amasty yang lebih tinggi.
Aaron Pollock
Ini kebiasaan buruk. Modul eksternal harus selalu tidak tersentuh. Jika Anda perlu memperbarui modul Anda, Anda harus mengulang semua perubahan Anda dalam versi baru. Ini mungkin menjadi mimpi buruk dalam hal perawatan.
Michael Türk
Anda sebaiknya membuat blok baru dan memperluasnya dari toolbar Amasty, bukan sebaliknya.
Amasty