Ganti kelas abstrak di Magento 2

13

Di Magento 1 saya bisa menyalin kelas abstrak ke direktori lokal atau komunitas dan Magento menggunakannya, ketika memuat secara otomatis kelas ini.

Apakah ada beberapa solusi untuk membuat Magento memuat kelas saya sebagai gantinya vendor/magento/framework/Model/AbstractModel.php?

Preferensi dalam di.xmluntuk kelas abstrak tidak berfungsi. Hanya plugin?

goral
sumber

Jawaban:

9

Hanya plugin?

Iya. Anda dapat menulis plugin untuk kelas abstrak dan plugin harus selalu lebih disukai daripada preferensi jika memungkinkan.

Preferensi berguna jika Anda ingin mengganti implementasi. Saya tidak bisa memikirkan use case untuk menggantikan implementasi untuk semua model yang diperluas AbstractModel, jika itu mungkin secara logis. Jadi yang mungkin Anda inginkan adalah menambah atau mengubah fungsi dan inilah gunanya plugin.

Fabian Schmengler
sumber
1
Hai, bagaimana saya bisa menimpa fungsi yang dilindungi dari kelas abstrak dalam hal ini? bisakah Anda membantu
Manashvi Birla
2
Itu tidak mungkin. Yang terbaik adalah mencoba menemukan cara untuk menambahkan plugin ke metode publik yang menggunakan metode yang dilindungi, dan mengubah perilaku dengan cara ini, bahkan jika itu melibatkan lebih banyak kode dan beberapa duplikasi.
Fabian Schmengler
1
"Saya tidak bisa memikirkan use case untuk menggantikan implementasi untuk semua model yang memperpanjang AbstractModel" Saya punya use case: Saya punya modul pembayaran, yang menggunakan kelas dasar abstrak untuk 4 pengendali, masing-masing menggunakan metode dari pangkalan untuk memverifikasi tanggapan dari gateway pembayaran. Sekarang, responsnya telah berubah dan saya harus mengubah semua 3.
Tero Lahtinen
6

Solusi lengkap: sertakan kelas yang diganti sebelum magento diisi ulang secara otomatis. Jadi langkah demi langkah:

  1. Dalam file app/etc/NonComposerComponentRegistration.phptambahkan baris

    $pathList[] = dirname(__DIR__) . '/etc/ClassReplacer.php';
  2. Di app/etctempat file ClassReplacer.phpdengan konten

    class ClassReplacer
    {
        public function includeReplacedFiles($src)
        {
            try {
                $replacedFiles = $this->listDir($src, false, true);
                foreach ($replacedFiles as $replacedFile) {
                    include_once $src . $replacedFile;
                }
            } catch (Exception $e) {
                return;
            }
        }
    
        protected function listDir($dir, $prependDir = false, $recursive = false, $entityRegexp = null, $currPath = '')
        {
            if (!is_dir($dir)) {
                return array();
            }
            $currPath = $prependDir ? $dir : $currPath;
            $currPath = $currPath !== '' ? rtrim($currPath, '/') . '/' : '';
            $files = array();
            foreach (scandir($dir) as $file) {
                if (in_array($file, array('.', '..'))) {
                    continue;
                }
                $entity = $currPath . $file;
                if ($recursive && is_dir("$dir/$file")) {
                    $files = array_merge($files, $this->listDir("$dir/$file", false, true, $entityRegexp, $entity . '/'));
                    continue;
                }
                if ($entityRegexp && !preg_match($entityRegexp, $entity)) continue;
                $files[] = $entity;
            }
            return $files;
        }
    }
    $replace = new ClassReplacer();
    $replace->includeReplacedFiles(dirname(__DIR__) . '/code/Magento/');
    
  3. Tempatkan ke app/code/Magentobeberapa kelas, yang akan diganti, misalnyaapp/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php

goral
sumber
1
Retasan kotor, tetapi beberapa kali mungkin bisa membantu untuk melakukan itu. M1 diperlukan perubahan manual di kelas inti (jadi salin ke aplikasi / kode / lokal) jika Anda ingin faktur PDF terlihat berbeda, saya yakin akan ada beberapa kasus di mana ini akan diperlukan.
Zefiryn
5

Jika kelas abstrak memiliki metode publik atau dilindungi yang ingin Anda timpa, ada cara sebenarnya jika Anda tidak dapat menggunakan plugin.

Saya harus mengganti metode _processDownloaddi dalam \Magento\Downloadable\Controller\Download, menambahkan beberapa 'jika-s' di dalamnya. (Jika ada yang tahu bagaimana saya bisa menambahkan sesuatu seperti ini di dalam metode menggunakan plugin saya akan berterima kasih). Kelas abstrak sehingga preferensi tidak berfungsi. Plugin juga, karena metode dilindungi. Hal yang harus saya lakukan adalah mengganti semua kelas dari Download, menggunakan preferensi. Kelas-kelas ini:

Magento\Downloadable\Controller\Download\Link Magento\Downloadable\Controller\Download\LinkSample Magento\Downloadable\Controller\Download\Sample

Dan di dalamnya menulis ulang metode dari kelas induk (yang seharusnya saya timpa). Jadi sebenarnya kode metode yang ditimpa disalin ke tiga tempat dan persis sama.

Itu tidak ideal tetapi, berhasil.

Bartosz Kubicki
sumber
4

Anda dapat mencoba menggunakan Plugin Magento untuk meningkatkan fungsionalitas yang ada dari setiap kelas Abstrak, meskipun cakupan fungsi harus Umum. Baru-baru ini saya bekerja pada masalah yang sama di mana saya harus mengecualikan produk yang memiliki atribut khusus yang ditetapkan dari daftar produk yang baru dilihat .

Saya menggunakan plugin untuk fungsi bernama getItemsCollection dari kelas bernama Magento \ Reports \ Block \ Product \ AbstractProduct menggunakan sintaks berikut:

file: app \ code \ Package \ Module \ etc \ frontend \ di.xml

<type name="Magento\Reports\Block\Product\AbstractProduct">
    <plugin name="Package_Module::aroundGetItemsCollection" type="Package\Module\Block\Viewed" sortOrder="20"/>
</type>

file: app \ code \ Package \ Module \ Block \ Dilihat.php

public function afterGetItemsCollection(
    $subject, $result
) {
    $result = $result->addAttributeToFilter('skip_hire_product', [['neq' => 1], ['null' => true]], 'left');
    return $result;
}

Anda dapat menggunakan sekitar juga sebelum plugin juga. Semoga ini berhasil untuk Anda.

Sumit Verma
sumber
1
saya mendapatkan sukses dengan kode di atas dalam salah satu persyaratan saya, sebenarnya saya ingin mengubah beberapa fungsionalitas metode email modul abstrak dan Plugin membantu saya untuk mencapai ini, terima kasih
bhargav shastri